如何在超类和子类中使用 std::enable_shared_from_this ?

oz1*_*1cz 5 c++ multiple-inheritance shared-ptr weak-ptr enable-shared-from-this

我有两个类A,B其中B是 的子类A。我需要两个类才能使用std::enable_shared_from_this。

我试过这个:

#include <memory>
#include <iostream>
#include <vector>


class A : public std::enable_shared_from_this<A> {
  public:
    void insertme(std::vector<std::shared_ptr<A>>& v) {
        std::cout << "A::insertme\n";
        v.push_back(shared_from_this());
        std::cout << "OK\n";
    }
};

class B : public A, public std::enable_shared_from_this<B> {
  public:
    void insertme(std::vector<std::shared_ptr<B>>& v) {
        std::cout << "B::insertme\n";
        v.push_back(std::enable_shared_from_this<B>::shared_from_this());
        std::cout << "OK\n";
    }
};

int main()
{
    std::vector<std::shared_ptr<A>> va;
    std::vector<std::shared_ptr<B>> vb;

    std::shared_ptr<A> pa = std::make_shared<A>();
    std::shared_ptr<B> pb = std::make_shared<B>();

    pa->insertme(va);
    pb->insertme(vb);
}
Run Code Online (Sandbox Code Playgroud)

(为了避免shared_from_this()出现歧义,我必须在 中对其进行完全限定B::insertme。)

当我运行上面的程序时,我得到以下输出:

A::insertme
OK
B::insertme
terminate called after throwing an instance of 'std::bad_weak_ptr'
  what():  bad_weak_ptr
Aborted (core dumped)
Run Code Online (Sandbox Code Playgroud)

所以A::insertme有效,但B::insertme没有。

我在Linux下使用GCC 9.1.0。

我究竟做错了什么?

Chr*_*odd 8

您只需要(并且只能)从基类中的shared_from_this继承:

class A : public std::enable_shared_from_this<A> {
  public:
    void insertme(std::vector<std::shared_ptr<A>>& v) {
        std::cout << "A::insertme\n";
        v.push_back(shared_from_this());
        std::cout << "OK\n";
    }
};

class B : public A {
  public:
    void insertme(std::vector<std::shared_ptr<B>>& v) {
        std::cout << "B::insertme\n";
        v.push_back(std::static_pointer_cast<B>(shared_from_this()));
        std::cout << "OK\n";
    }
};
Run Code Online (Sandbox Code Playgroud)

这意味着您需要显式地static_pointer_cast获取 a ,但如果您愿意,shared_ptr<B>您可以将其包装到重写中:B

std::shared_ptr<B> shared_from_this() { return std::static_pointer_cast<B>(A::shared_from_this()); }
Run Code Online (Sandbox Code Playgroud)