找出c ++中两个对象类之间的继承关系

时间:2010-11-07 11:23:24

标签: c++ reflection inheritance

我有一个抽象的C ++基类CPlugin。从中可以直接和间接地衍生出许多类。现在给出CPlugin * a,* b我需要找出,如果一个真正的类来自b的真实类。

即。我想做这样的事情:

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

但是如何在C ++中实现“getClass”和“isDerivedFrom”?

5 个答案:

答案 0 :(得分:5)

你不能用C ++做到这一点。在运行时获取有关类型的一些信息的唯一方法是RTTI。虽然RTTI不够强大,无法满足您的需求。请解释一下你想要达到的目标,然后你会得到更好的答案。

答案 1 :(得分:3)

整个解决方案很难提供。您要实现的是一种取决于两个参数的具体类型的行为:这称为双重调度。现代C ++设计的几页(Andrei Alexandrescu)致力于这个子喷射。

一旦在单个代码点知道两个参数的实际具体类型,就可以使用boost type_traits来回答“isDerivedFrom”部分:boost is_base_of

答案 2 :(得分:2)

您可以使用动态强制转换来测试对象是否属于编译时已知类型的子类型。根据对象的运行时类型更改行为的机制是一个虚函数,它为您提供了一个在编译时已知接收器类型的范围。

因此,您可以通过虚函数实现相同的效果,因此您在一侧编译时具有类型,然后使用动态强制转换来检查另一侧的类型:

#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;
}

(您还可以添加T扩展TypedPlugin<T>

的支票

虽然dynamic_cast在其参数上是运行时多态的,所以它并不是一个双重调度,所以它非常接近。

虽然对于任何更复杂的事情(或者如果你想坚持比较表示你拥有的对象的运行时类型的对象的原始风格),你需要开始创建元类,或者使用现有的框架供应元类。由于您正在谈论插件,您可能已经在某处指定配置属性或依赖项,并且也可以使用它。

答案 3 :(得分:0)

答案 4 :(得分:0)

我真的不明白你的目标,但你总是可以用以下方式使用虚拟方法:

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

现在,使用以下纯虚方法扩充CPlugin类:

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

并使每个来自CPlugin的类继承自TypeChecker

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

最后像这样使用它:

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

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

但这并不能检测它是否是一个特化,因为两者完全属于完全相同的类,这可以通过使用typeid运算符来检测。

请注意为从CPlugin派生的每个类实现它的要求,您将理解为什么它如此复杂且容易出错......