如何检测和断言特定类的虚拟继承?

Posted

技术标签:

【中文标题】如何检测和断言特定类的虚拟继承?【英文标题】:How to detect and assert virtual inheritance for a specific class? 【发布时间】:2011-12-19 09:45:12 【问题描述】:

我有一个实现引用计数的 C++ 类,我希望这个类的所有用户只虚拟地从这个类继承,这样任何对象都不会有多个引用计数器。

我想通过某种方式在编译时或至少在运行时声明此要求。

有没有办法做到这一点?

【问题讨论】:

【参考方案1】:

这样的?

struct RefCounter 
    template <typename T>
    RefCounter(T *) 
        BOOST_STATIC_ASSERT(boost::is_virtual_base_of<RefCounter, T>);
    
;

struct GoodClass : virtual RefCounter 
    GoodClass() : RefCounter(this) 
;

struct BadClass : RefCounter 
    BadClass() : RefCounter(this) 
;

很遗憾,需要将this 传递给构造函数来捕获派生类型。当然,一个故意迟钝的用户可以通过传递 this 以外的其他内容来颠覆它。

【讨论】:

您可以使用 CRTP 代替 this,但我认为您的解决方案更好。 @sbi:我考虑过,但是RefCounter&lt;Derived&gt;RefCounter&lt;DoublyDerived&gt; 将是不同的类,因此即使它们是虚拟的,您仍然可以得到多个 refcounter 基类子对象。跨度> 如果一个类从两个基类继承,一个基类从RefCounter 虚拟继承而另一个非虚拟继承,这会起作用吗? @sharptooth:“其他”类应该触发断言,因此您甚至不会达到从它们两者继承的类的程度。 这个解决方案看起来很棒,除了一件事 - 它需要实际更改已经从 RefCounter 继承的每个类,而且工作量很大。【参考方案2】:

我认为包装类是最简单的选择。与其直接从 RefCounter 继承,不如创建一个中间类。

struct RefCounterVirtPrivate_

    int count;

    RefCounterVirt()
        : count( 0 )
     
;

struct RefCounter : public virtual RefCounterVirtPrivate_

;

struct A : public RefCounter  ;
struct B : public RefCounter  ;
struct C : public A, public B  ;

那么一切都可以从RefCounter继承,而无需关心虚拟继承。您甚至不必更改任何现有代码——RefCounter 本身的虚拟继承应该是无害的。

这当然不能保证人们不会直接从RefCounterVirtPrivate_ 继承,但这就是为什么我给它起了一个明显的名字。不小心这样做比忘记 virtual 关键字更难。

【讨论】:

【参考方案3】:

这应该是可能的,但请考虑其中的含义:您正在设置该对象需要在其引用计数器达到零时立即自毁的策略。

根据您的应用程序,您可能希望将调用 delete this; 的确切时间留给对象的实现,即在基类中只有 add_ref()release() 抽象函数(这使得具体实现显示在所有接口 vtable 中,并带有适当的 thunking),并将维护引用计数的负担放在具体类上。

【讨论】:

实际上这个类在任何时候都在做delete this,所以我可以在addref()/release()中进行检查。所以这个诡计是受欢迎的。

以上是关于如何检测和断言特定类的虚拟继承?的主要内容,如果未能解决你的问题,请参考以下文章

虚拟继承中派生类的大小

C++进阶:继承C++为什么要引入继承 | 继承概念及定义 | 基类和派生类对象赋值转换 | 继承中的作用域 | 派生类的默认成员函数 | 继承与友元/静态成员 | 复杂的菱形继承及菱形虚拟继承

C++进阶:继承C++为什么要引入继承 | 继承概念及定义 | 基类和派生类对象赋值转换 | 继承中的作用域 | 派生类的默认成员函数 | 继承与友元/静态成员 | 复杂的菱形继承及菱形虚拟继承

C++进阶:继承C++为什么要引入继承 | 继承概念及定义 | 基类和派生类对象赋值转换 | 继承中的作用域 | 派生类的默认成员函数 | 继承与友元/静态成员 | 复杂的菱形继承及菱形虚拟继承

C++进阶:继承C++为什么要引入继承 | 继承概念及定义 | 基类和派生类对象赋值转换 | 继承中的作用域 | 派生类的默认成员函数 | 继承与友元/静态成员 | 复杂的菱形继承及菱形虚拟继承

从继承的类中覆盖虚拟方法但保留基类的注释[重复]