检查派生类型(C ++)

时间:2010-03-01 10:43:30

标签: c++ design-patterns

如果对象是ClassA类型或派生类型ClassB,我如何在运行时检查?在一种情况下,我必须单独处理两个实例

ClassA* SomeClass::doSomething ( ClassA* )
{
    if( /* parameter is of type base class */) {

    } else if { /* derived class */ ) {

    }
}

也许我可以说派生类ClassB具有一些特殊功能。但是,如何在不更改现有类ClassA的情况下执行此操作?

6 个答案:

答案 0 :(得分:22)

打开这样的确切类型通常是一个非常糟糕的主意。通过这样做,您将方法与ClassA的派生类紧密耦合。你应该使用多态。在A类中引入virtual方法,在B类中重写它,然后在方法中调用它。

即使我因某种原因被迫处理外部函数本身的功能,我也会这样做:

class ClassA { 
  public: virtual bool hasSpecificFunctionality() { return false; }
};

class ClassB : public ClassA {
  public: virtual bool hasSpecificFunctionality() { return true; }
};

ClassA* SomeClass::doSomething ( ClassA* arg )
{
    if (arg->hasSpecificFunctionality()) {

    } else {

    }
}

答案 1 :(得分:15)

使用dynamic_cast,如下所示:

ClassA* SomeClass::doSomething(ClassA* a)
{
    if (dynamic_cast<DerivedClass*>(a)) {
        ...
    } else if (dynamic_cast<BaseClass*>(a)) {
        ...
    }
 }
如果dynamic_cast<T *>(ptr)不是0类型的指针,

ptr将返回T,否则将返回T类型的指针。

通常可以避免

dynamic_cast,这是设计/代码设计不良的指标。如果可以避免,请尝试这样做,因为在最终的可执行文件中需要RTTI

答案 2 :(得分:4)

为什么不在ClassB上使用doSomething()方法来处理ClassB的额外功能?这是多态性的本质。

答案 3 :(得分:3)

语法是:

ClassA* SomeClass::doSomething ( ClassA* pa )
{
    ClassB* pb = dynamic_cast<ClassB*>(pa);
    if( pb ) ...

(请注意,这只适用于多态类层次结构。也就是说,必须涉及虚函数。)

但是,你应该尽量避免这种情况。你需要什么才能通过应用虚函数来解决?

答案 4 :(得分:3)

其他人指出,开启类型通常是一个坏主意,所以我不会。如果你真的必须这样做,你可以使用typeid运算符来打开对象的动态类型:

ClassA* SomeClass::doSomething ( ClassA* a )
{
    if (typeid(*a) == typeid(ClassA)) {
        /* parameter is of type base class */
    } else if (typeid(*a) == typeid(ClassB)) {
        /* a specific derived class */ 
    } else {
        /* some other derived class */
    }
}

dynamic_cast类似,但测试可兑换性,而不是相等性:

ClassA* SomeClass::doSomething ( ClassA* a )
{
    if (ClassB *b = dynamic_cast<classB*>(a)) {
        /* parameter is, or is derived from, ClassB */
    } else {
        /* parameter is, or is derived from, ClassA but not ClassB */ 
    }
}

仅当ClassA具有多态性(即,它至少有一个虚函数)时,这些才有效。

答案 5 :(得分:2)

Slighlty与你要求的不同

ClassB* b;
if ((b = dynamic_cast<ClassB*>(ptr)) == 0) {
    // not a classB*
} else {
    // a classB* in b
}
相关问题