enable_shared_from_this的双重继承

Double inheritance of enable_shared_from_this

本文关键字:继承 this shared from enable      更新时间:2023-10-16

我有一个对象(Z(,它派生自另外两个对象(A和B(。

A和B都分别从enable_shared_from_this<>enable_shared_from_this<A>enable_shared_from_this<B>导出。

当然,我在Z上调用shared_from_this()。当然,编译器报告这是不明确的。

我的问题是:

  • enable_shared_from_this<>继承两次是否安全,还是创建两个分开的引用计数(错误!(
  • 如果不安全,我该如何解决

注:当基类和派生类都从boost::enable_shared_from_this继承时,我发现另一个问题是坏的弱指针,但它并没有真正回答。我也应该使用virtual技巧吗?

是的,根据坏的弱指针,当基类和派生类都继承自boost::enable_shared_from_this解决方案是使用虚拟继承。以下是C++11标准shared_ptr(而非Boost(的实现:

#include <memory>
struct virtual_enable_shared_from_this_base:
   std::enable_shared_from_this<virtual_enable_shared_from_this_base> {
   virtual ~virtual_enable_shared_from_this_base() {}
};
template<typename T>
struct virtual_enable_shared_from_this:
virtual virtual_enable_shared_from_this_base {
   std::shared_ptr<T> shared_from_this() {
      return std::dynamic_pointer_cast<T>(
         virtual_enable_shared_from_this_base::shared_from_this());
   }
};
struct A: virtual_enable_shared_from_this<A> {};
struct B: virtual_enable_shared_from_this<B> {};
struct Z: A, B { };
int main() {
   std::shared_ptr<Z> z = std::make_shared<Z>();
   std::shared_ptr<B> b = z->B::shared_from_this();
}

这不是默认实现的一部分,可能是因为虚拟继承的开销。

是的,您的类将从两个不同的类enable_shared_from_this<A>enable_shared_from_this<B>派生,并具有两个不同弱ref的

这个答案的诀窍是允许有一个基类,因为虚拟继承

使用shared_ptr别名构造函数,可以导出ecatmur答案的变体:

#include <memory>
struct virtual_enable_shared_from_this_base:
   std::enable_shared_from_this<virtual_enable_shared_from_this_base> {
   virtual ~virtual_enable_shared_from_this_base() {}
};
template<typename T>
struct virtual_enable_shared_from_this:
virtual virtual_enable_shared_from_this_base {
   std::shared_ptr<T> shared_from_this() {
      return std::shared_ptr<T>(
         virtual_enable_shared_from_this_base::shared_from_this(),
         static_cast<T*>(this));
   }
   std::shared_ptr<const T> shared_from_this() const {
      return std::shared_ptr<const T>(
         virtual_enable_shared_from_this_base::shared_from_this(),
         static_cast<const T*>(this));
   }
};
struct A: virtual_enable_shared_from_this<A> {};
struct B: virtual_enable_shared_from_this<B> {};
struct Z: A, B { };
int main() {
   std::shared_ptr<Z> z = std::make_shared<Z>();
   std::shared_ptr<B> b = z->B::shared_from_this();
}

我预计这个版本在很多情况下会更快,因为它避免了代价高昂的动态转换。然而,和往常一样,只有基准才有最终决定权。此外,我还添加了const变体。