Check for derived type (C++)

前端 未结 6 626
暗喜
暗喜 2020-12-09 12:18

How do I check at runtime if an object is of type ClassA or of derived type ClassB? In one case I have to handle both instances separately

ClassA* SomeClass:         


        
相关标签:
6条回答
  • 2020-12-09 12:44

    The syntax is this:

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

    (Note that this only works within polymorphic class hierarchies. That is, there have to be virtual functions involved.)

    However, you should try to avoid that. What do you need it for that cannot be solved by applying virtual functions?

    0 讨论(0)
  • 2020-12-09 12:46

    It's generally a very bad idea to switch on the exact type like that. By doing this, you are tightly coupling your method to derived classes of ClassA. You should use polymorphism. Introduce a virtual method in class A, override it in class B and simply call it in your method.

    Even if I was forced to handle the functionality in the external function itself for some reason, I would do something like:

    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 {
    
        }
    }
    
    0 讨论(0)
  • 2020-12-09 12:49

    Others have pointed out that switching on types is usually a bad idea, so I won't. If you really have to do it, you can use the typeid operator to switch on the dynamic type of an object:

    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 is similar, but tests for convertibility, not equality:

    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 */ 
        }
    }
    

    These only work if ClassA is polymorphic (that is, it has at least one virtual function).

    0 讨论(0)
  • 2020-12-09 12:55

    Slighlty different that what you asked for

    ClassB* b;
    if ((b = dynamic_cast<ClassB*>(ptr)) == 0) {
        // not a classB*
    } else {
        // a classB* in b
    }
    
    0 讨论(0)
  • 2020-12-09 12:57

    Why not have a doSomething() method on ClassB that handles ClassB's extra capabilities? This is the essence of polymorphism.

    0 讨论(0)
  • 2020-12-09 13:00

    Use a dynamic_cast as follows:

    ClassA* SomeClass::doSomething(ClassA* a)
    {
        if (dynamic_cast<DerivedClass*>(a)) {
            ...
        } else if (dynamic_cast<BaseClass*>(a)) {
            ...
        }
     }
    

    dynamic_cast<T *>(ptr) will return 0 in case ptr is not a pointer of type T, and will return a pointer of type T otherwise.

    dynamic_cast can usually be avoided and is an indicator of bad design / code. If you can avoid it, try to do so, as it requires RTTI in your final executable.

    0 讨论(0)
提交回复
热议问题