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

发布于 2024-12-21 19:01:44 字数 114 浏览 2 评论 0原文

我有一个实现引用计数的 C++ 类,并且我希望该类的所有用户仅从该类虚拟继承,以便没有对象最终拥有多个引用计数器。

我想要某种方法来在编译时或至少在运行时断言此要求。

有办法实现吗?

I have a C++ class that implements reference-counting and I want all users of this class to inherit from this class only virtually so that no object ends up with more than one reference counter.

I'd like some way to assert this requirment either during compile time or at least during runtime.

Is there a way to achieve that?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

乖乖哒 2024-12-28 19:01:44

像这样的东西吗?

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 以外的其他内容来破坏它。

Something like this?

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) {}
};

It's a shame about needing to pass this to the constructor, though, to capture the derived type. And of course a wilfully obtuse user could subvert it by passing something other than this.

缘字诀 2024-12-28 19:01:44

我认为包装类将是最简单的选择。而不是直接继承自 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 关键字更难。

I think wrapping the class would be the simplest option. Rather than directly inheriting from RefCounter create an intermediary class.

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

Then everything can inherit from RefCounter without any need to care about virtual inheritence. You don't even have to change any existing code -- virtual inheritence of RefCounter itself should be harmless.

This of course doesn't guarantee people don't inherit from RefCounterVirtPrivate_ directly, but that is why I've given it an obvious name. It's harder to accidentally do this than forget a virtual keyword.

软糖 2024-12-28 19:01:44

通过一些技巧应该可以实现,但请考虑其含义:您正在设置策略,如果对象的引用计数器达到零,则该对象需要立即自毁。

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

It should be possible with some trickery, but consider the implications: you are setting the policy that the object needs to immediately self-destruct if its reference counter ever reaches zero.

Depending on your application, you might want to leave the exact time when it calls delete this; to the implementation of the object, i.e. only have add_ref() and release() abstract functions in the base class (which makes the one concrete implementation show up in all interface vtables with proper thunking) and place the burden of maintaining the reference count on the concrete class.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文