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

How can I use std::enable_shared_from_this in both super and subclass?

我有两个 类 AB,其中 BA 的子类。我需要 类 才能使用 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);
}

(为了避免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)

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

我在 Linux 下使用 GCC 9.1.0。

我做错了什么?

您只需要(也只能)在基 class:

中继承 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";
    }
};

这意味着您需要明确的 static_pointer_cast 才能获得 shared_ptr<B>,但如果需要,您可以将其包装到 B 中的覆盖中:

std::shared_ptr<B> shared_from_this() { return std::static_pointer_cast<B>(A::shared_from_this()); }

创建 shared_ptr<T> 时设置的到 enable_shared_from_this<X> 的自动链接仅在 class 类型 T 恰好继承一个明确的 public enable_shared_from_this基地。但是 B 继承了两个不同的 enable_shared_from_this 基础。

相反,您可以只使用 enable_shared_from_this<A>,并编写一个使用 A::shared_from_this():

的自定义 B::shared_from_this()
class B : public A {
  public:
    // These hide the A::shared_from_this(), but they can still be
    // used by qualification if wanted.
    std::shared_ptr<B> shared_from_this()
    { return std::static_pointer_cast<B>(A::shared_from_this()); }
    std::shared_ptr<const B> shared_from_this() const
    { return std::static_pointer_cast<B>(A::shared_from_this()); }

    // ...
};