enable_shared_from_this的双重继承

时间:2013-03-21 14:03:34

标签: c++ shared-ptr

我有一个对象(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<>继承两次是安全的,还是会创建两个分开的引用计数(不好!)
  • 如果不安全,我该如何解决?

注意: 我发现了另一个问题bad weak pointer when base and derived class both inherit from boost::enable_shared_from_this,但它并没有真正回答。我也应该使用virtual技巧吗?

3 个答案:

答案 0 :(得分:13)

是的,根据bad weak pointer when base and derived class both inherit from 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();
}

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

答案 1 :(得分:1)

是的,你的班级将来自两个不同的班级enable_shared_from_this<A>enable_shared_from_this<B>,并且有两个不同的弱参考

由于虚拟继承

,该答案的诀窍允许有一个基类

答案 2 :(得分:0)

使用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();
}

我希望该版本在许多情况下都可以更快,因为它避免了昂贵的动态转换。但是,像往常一样,只有becnhmarks具有最后的词。另外,我添加了const变体。