10

我有一个从其他两个对象(A 和 B)派生的对象(Z)。

enable_shared_from_this<>A 和 B 都分别来自enable_shared_from_this<A>enable_shared_from_this<B>

当然,我会调用shared_from_this()Z。当然,编译器会将此报告为模棱两可的。

我的问题是:

  • 继承两次是安全的enable_shared_from_this<>还是会创建两个单独的引用计数(不好!)
  • 如果不安全,我该如何解决?

注意:当基类和派生类都继承自 boost::enable_shared_from_this但它并没有真正回答时,我发现了另一个问题bad weak pointer。我也应该使用这个virtual技巧吗?

4

3 回答 3

15

是的,根据当基类和派生类都从 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();
}

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

于 2013-03-21T14:27:50.260 回答
1

是的,你的类将派生自两个不同的类enable_shared_from_this<A>and enable_shared_from_this<B>,并且有两个不同的弱引用

由于虚拟继承,该答案的技巧允许拥有一个基类

于 2013-03-21T14:20:00.250 回答
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变体。

于 2019-04-15T15:31:45.217 回答