如何检测和断言特定类的虚拟继承?
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<Derived>
和RefCounter<DoublyDerived>
将是不同的类,因此即使它们是虚拟的,您仍然可以得到多个 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++为什么要引入继承 | 继承概念及定义 | 基类和派生类对象赋值转换 | 继承中的作用域 | 派生类的默认成员函数 | 继承与友元/静态成员 | 复杂的菱形继承及菱形虚拟继承