【发布时间】:2020-01-02 12:54:19
【问题描述】:
我试图理解为什么在调用shared_from_this 时会出现bad_weak_ptr 异常。
#include <memory>
#include <iostream>
class parent : public std::enable_shared_from_this<parent>
{
public:
void compare(std::shared_ptr<parent> const& p2)
{
std::cout << (this->shared_from_this() == p2->shared_from_this());
}
};
class child1 : public parent
{};
class child2 : public parent
{};
class child3 : public child1, public child2
{};
void compare(parent& p1, parent& p2)
{
std::cout << &p1 << " : " << &p2 << "\n";
std::cout << (&p1 == &p2);
}
void compare(std::shared_ptr<parent> const& p1, std::shared_ptr<parent> const& p2)
{
compare(*p1, *p2);
// p1->compare(p2); // bad_weak_ptr
// auto p = p1->shared_from_this(); // bad_weak_ptr
}
void compareusingchild(std::shared_ptr<child1> const& c1, std::shared_ptr<child2> const& c2)
{
compare(c1, c2);
}
int main()
{
std::shared_ptr<child3> c3 = std::make_shared<child3>();
try
{
compareusingchild(c3, c3);
}
catch (std::exception& e)
{
std::cout << e.what();
}
return 0;
}
我发现通过使class parent 继承虚拟化,这个问题似乎不会持续存在。为什么这不是编译时错误?当找不到正确的继承父对象时,类似于“模糊函数调用”?
仅包含父类的 API 无法提前知道继承层次结构,调用 compare 方法(在父类中)将导致运行时错误。是否有可能在编译时检测到此类错误?
【问题讨论】:
-
这是一个钻石问题。由于您的继承不是虚拟的
child3有两个parent组件(一个来自child1一个来自child2),因此您有两个std::enable_shared_from_this组件。请注意您以不正确的方式使用std::enable_shared_from_this。当您调用std::make_shared<child3>();时,只有一个版本的std::enable_shared_from_this已被初始化。 -
我在使用 c++14 时确实遇到了编译错误 onlinegdb.com/rkecnzBBB
error: ‘std::enable_shared_from_this’ is an ambiguous base of ‘child3’,但使用 c++17 时它编译得很好:( -
@ustulation 到目前为止我只使用 MSVS 2017 编译。既然您说了,我也尝试了 c++ 11,但它无法编译。所以这个问题与我的应用程序无关,因为它在 c++11 中。我还想知道c++17有什么变化?
-
@ustulation 令人惊讶地编译:godbolt.org/z/Z7MztH
-
@MarekR 我同意这是一个钻石问题。编译器不应该检测到它吗?
标签: c++ shared-ptr multiple-inheritance ambiguous enable-shared-from-this