【问题标题】:Is there a way to find out whether a class is a direct base of another class?有没有办法找出一个类是否是另一个类的直接基础?
【发布时间】:2011-01-16 17:59:16
【问题描述】:

我想知道是否有办法找出一个类是否是另一个类的直接基础,即在 Boost 类型特征术语中是 is_direct_base_of 函数。据我所知,Boost 似乎不支持这种功能,这让我认为当前的 C++ 标准是不可能的。

我想要它的原因是对用于反射系统的两个宏进行一些验证检查,以指定一个类派生自另一个类,如下面的示例代码所示。

header.h:

#define BASE     A
#define DERIVED  B

class A {};
class B : public A 
{
   #include <rtti.h>
};

rtti.h:

// I want to check that the two macro's are correct with a compile time assert
Rtti<BASE, DERIVED> m_rtti;

虽然在这个简单的例子中宏似乎没有必要,但在我的真实世界场景中rtti.h 要复杂得多。

一种可能的方法是将 this 指针的大小与转换为基类型的 this 指针的大小进行比较,并以某种方式试图弄清楚它是否是基类本身的大小或其他东西。 (是的,你是对的,我也不知道那会怎样!)

【问题讨论】:

    标签: c++ templates boost metaprogramming


    【解决方案1】:

    我问自己,“哪些 C++ 构造可以区分直接继承和间接继承?”请记住,派生类型的 C++ 构造函数仅直接调用其直接基类的构造函数。所以代码如下:

    Derived::Derived() : Base() {}
    

    仅当Base 是Derived 的直接基时才有效。并且由于您将rtti.h 的代码注入Derived 的主体中,因此您可以容忍这种技术仅在派生类本身中直接可见的限制(即它不像假设的type_traits::is_direct_base_of 那样通用,但不需要)。

    既然我们可能不想乱用默认构造函数本身,那么添加一些特殊用途的构造函数怎么样?

    #define BASE     A
    #define DERIVED  B
    
    struct rtti_tag {}; // empty type
    
    class A
    {
    protected:
        A(rtti_tag) { assert(false); } // never actually called
    };
    
    #include <rtti.h>
    class B : public A
    {
        IS_DIRECT_BASE_OF(DERIVED, BASE); // fails to compile if not true
    };
    

    rtti.h:

    #define IS_DIRECT_BASE_OF(_B_, _A_) _B_(rtti_tag tag) : _A_(tag) \
        { assert(false); } // never actually called
    

    此代码使用 g++ 4.2 为我编译;如果我在继承层次结构中插入一个新类,则断言中断并且编译失败,我认为这是一个合理的描述性诊断:

    In constructor ‘B::B(rtti_tag)’:
    error: type ‘A’ is not a direct base of ‘B’
    ...
    

    【讨论】:

    • Derived::Derived() : Base() {} 如果Base 是一个非直接的虚拟基类也有效——可能这种情况可以通过(又一个)测试来消除?无论如何 +1。
    • 好点,j_random_hacker,这很聪明(或邪恶!)。我不知道如何解决这个“问题”,但希望它是一个病态的事情,它并不真正需要解决(C ++是一种恶意的语言,几乎可以把任何事情弄得一团糟) .
    • 我同意,这是一个病态的病例,你不需要为此失眠。我之所以想到它,是因为我曾经看到一个技巧来防止从一个类中进一步派生(即强制它成为一个“叶子”),它也被虚拟继承颠覆了。 VI 确实有点像语言设计技巧——例如分配派生类的对象时,虚拟基类的operator=() 将被调用次数不定。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-12-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多