检查派生类型(C++)

Sne*_*ney 7 c++ design-patterns

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

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

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

    }
}
Run Code Online (Sandbox Code Playgroud)

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

Meh*_*ari 23

打开这样的确切类型通常是一个非常糟糕的主意.通过这样做,您将方法与派生类紧密耦合ClassA.你应该使用多态.virtual在A类中引入一个方法,在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 {

    }
}
Run Code Online (Sandbox Code Playgroud)

  • @Poita_:如果你不能改变基类,也许你应该首先使用组合而不是继承. (2认同)

Ton*_*vel 17

使用dynamic_cast如下:

ClassA* SomeClass::doSomething(ClassA* a)
{
    if (dynamic_cast<DerivedClass*>(a)) {
        ...
    } else if (dynamic_cast<BaseClass*>(a)) {
        ...
    }
 }
Run Code Online (Sandbox Code Playgroud)

dynamic_cast<T *>(ptr)将返回0以防万一ptr不是类型T的指针,T否则将返回一个类型的指针.

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

  • 但请记住,dynamic_cast的参数必须是多态类(即具有至少一个虚方法的类)的指针(或引用).否则dynamic_cast将失败. (5认同)
  • 在转换为`BaseClass`之前,你需要尝试使用强制转换为`DerivedClass`,因为`BaseClass`强制转换将对任一类型都成功. (3认同)

Mik*_*our 8

其他人指出切换类型通常是一个坏主意,所以我不会。如果你真的必须这样做,你可以使用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 */
    }
}
Run Code Online (Sandbox Code Playgroud)

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 */ 
    }
}
Run Code Online (Sandbox Code Playgroud)

这些只有在ClassA是多态的情况下才有效(也就是说,它至少有一个虚函数)。