开发者

Find out inheritance relation between two objects classes in c++

I've got an abstract C++ base class CPlugin. From it, there are many classes derived directly and indirectly. Now given CPlugin *a,*b I need to find out, if a's real class is derived from b's r开发者_StackOverfloweal class.

I.e. I'd like to do something like this:

void checkInheritance(CPlugin *a, CPlugin *b){
  if (getClass(a).isDerivedFrom(getClass(b)){
    std::cout << "a is a specialization from b's class" << std::endl;
  }
}

But how do I implement the "getClass" and "isDerivedFrom" in C++?


You cannot do this in C++. The only way to get some information about types on runtime is RTTI. RTTI is not powerful enough to do what you need though. Please explain what you are trying to achieve, then you will get better answers.


A whole solution is really tough to provide. What you are trying to achieve is a behavior that depends on the concrete type of two parameters : this is called double dispatch. A few pages of Modern C++ Design (Andrei Alexandrescu) are devoted to this subjet.

Once the actual concrete type of both parameters are known at a single code point, the "isDerivedFrom" part can be answered using boost type_traits : boost is_base_of.


You can use dynamic cast to test whether an object belongs to a subtype of a type known at compile time. The mechanism for changing behaviour depending on the runtime type of an object is a virtual function, which gives you a scope where the type of the receiver is known at compile time.

So you can achieve the same effect by a virtual function so you have the type at compile time on one side, and then dynamic cast to check the other side against that type:

#include <iostream>

class Plugin {
    public:
    virtual bool objectIsDerivedFromMyClass ( const Plugin & object ) const = 0;
};

template <typename T, typename BasePlugin = Plugin>
class TypedPlugin : public BasePlugin {
    public:
    virtual bool objectIsDerivedFromMyClass ( const Plugin & object ) const {
        return dynamic_cast<const T*> ( &object ) != 0;
    }

    private:
        int CheckMe(const T*) const;
};

class PluginA : public TypedPlugin<PluginA> {};
class PluginB : public TypedPlugin<PluginB, PluginA> {};
class PluginC : public TypedPlugin<PluginC> {};

int main () {
    PluginA a;
    PluginB b;
    PluginC c;

    std::cout << std::boolalpha
    << "type of a is derived from type of a " <<  a.objectIsDerivedFromMyClass ( a ) << '\n'
    << "type of a is derived from type of b " <<  b.objectIsDerivedFromMyClass ( a ) << '\n'
    << "type of b is derived from type of a " <<  a.objectIsDerivedFromMyClass ( b ) << '\n'
    << "type of c is derived from type of a " <<  a.objectIsDerivedFromMyClass ( c ) << '\n'
    ;

    return 0;
}

(You also may want to add a check that T extends TypedPlugin<T>)

It's not quite double dispatch, though dynamic_cast is runtime polymorphic on its argument so it is pretty close.

Though for anything much more complicated (or if you want to stick with your original style of comparing the objects which represent the runtime types of the objects you have), you need to start create metaclasses, or use an existing framework which supplies metaclasses. Since you're talking about plugins, you may already have somewhere to specify configuration properties or dependencies, and that could be used for this too.


Typeinfo and dynamic cast: http://www.cplusplus.com/reference/std/typeinfo/type_info/


I don't really understand what you are after, but you can always use virtual methods in the following manner:

template <typename Derived>
struct TypeChecker
{
  virtual bool ParentOf(CPlugin const& c) const
  {
    return dynamic_cast<Derived const*>(&c);
  }
};

Now, augment the CPlugin class with the following pure virtual method:

  virtual bool ParentOf(CPlugin const& c) const = 0;

And make each class deriving from CPlugin inherit from TypeChecker as well:

class SomePlugin: public CPlugin, private TypeChecker<SomePlugin> {};

And finally use it like such:

void checkInheritance(CPlugin const& lhs, CPlugin const& rhs)
{
  if (!rhs.ParentOf(lhs)) return;

  std::cout << "lhs is derived from rhs' class\n";
}

This does not detect if it is a specialization though, since both could perfectly be of the exact same class, this can be detected by using the typeid operator.

Note the requirement to implement it for every single class deriving from CPlugin and you'll understand why it is so complicated and error-prone...

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜