C++ 从std::enable_shared_和抽象基类派生出来可以吗?
我正在编写一个应该派生自抽象基类的类。我无法更改抽象基类。该类将作为抽象基类的C++ 从std::enable_shared_和抽象基类派生出来可以吗?,c++,smart-pointers,C++,Smart Pointers,我正在编写一个应该派生自抽象基类的类。我无法更改抽象基类。该类将作为抽象基类的共享\u ptr。可以从抽象基类继承吗?像这样: class IWidget { public: virtual ~IWidget(){} // ... }; class Widget : public std::enable_shared_from_this<Widget>, public IWidget { protected: Widget(); // protected, use c
共享\u ptr
。可以从抽象基类继承吗?像这样:
class IWidget {
public:
virtual ~IWidget(){}
// ...
};
class Widget : public std::enable_shared_from_this<Widget>, public IWidget {
protected:
Widget(); // protected, use create
public:
static std::shared_ptr<IWidget> create() {
return std::shared_ptr<IWidget>(new Widget(init));
}
// ...
};
当我尝试从\u this()使用shared\u时,我遇到运行时错误。
。我认为这是有道理的shared_ptr
具有接受“可转换”指针的。除非shared\u ptr
构造函数知道它正在使用小部件
,否则它不知道它是从中派生出来的,并且它不能存储弱的\u ptr
。我只是想知道这种行为是否被记录在案。是的。如果没有人依赖未定义的行为,那就好了。现在,严格地说,若你们使用UB,你们的代码已经被破坏了,但在实践中,多重继承使得很多无效的假设变得更加明显
我特别想到
Base* p = this;
Derived* pDerived = reinterpret_cast<Derived*>(p);
Base*p=this;
派生*pDerived=重新解释铸造(p);
可能无法按预期工作。它需要是静态的
是的,它绝对好
shared_ptr
有一个模板化构造函数,它接受一个“可转换”指针。除非shared\u ptr
构造函数知道它正在使用小部件
,否则它不知道它是从中派生出来的,并且它不能存储弱的\u ptr
完全正确
我只是想知道这种行为是否有记录
在当前标准中,enable_shared_from_,this
的规定非常糟糕,但请参阅C++17中的enable_shared_from_,this
的新的和改进的规范。除了回答“如果执行两次会发生什么?”问题外,修订后的措辞还明确说明了如何使用此
基类中的enable\u shared\u,以及如何初始化weak\u ptr
成员。新措辞的这一部分只是对现有实践的标准化,也就是说,它只是对实际实现已经做了什么的更准确描述。(对“如果执行两次会发生什么情况?”问题的回答与以前的实现有所不同,但有充分的理由,这与您的问题无关)
新规范澄清了您的原始示例是完全定义良好且正确的
当前标准规定,当您从_this()
调用shared_时,更新问题中的修改版本具有未定义的行为,这是因为违反了拥有指向派生的指针的shared_ptr
的先决条件(因为您创建了拥有指向基的指针的shared_ptr
)。然而,正如本文所解释的那样,这一前提条件不足以确保合理的语义。修改后的措辞使您的修改版本也得到了很好的定义(即没有未定义的行为),但是基类中的弱ptr
不会与共享ptr
共享所有权,因此共享ptr from_this()
将抛出异常(这是您从实现中观察到的).您是否应该继承自std::enable_shared_from_this
,以便Widget::shared_from_this()
返回std::shared_ptr
(您当前获得的)而不是std::shared_ptr
?@user4815162342主要目的是在从小部件
中创建的lambda中捕获共享的ptr
,以确保小部件
的寿命与lambda一样长。在该lambda中,我可能希望调用IWidget
上不可用的本地成员函数。我认为应该可以,只要小部件
在析构函数中未清理资源的情况下,对取消分配没有特殊处理。没有基类。在多重继承的情况下使用从\u this启用\u shared\u没有问题。这与OP的要求相去甚远。您的示例有一个定义良好的行为。如果涉及多重继承,并且Base不是派生类的第一个基类,我认为它没有定义良好的行为。你能为这样做提供一些章节吗?我的观点是,在多重继承中(这是OP所问的),启用了来自于的共享在多重继承中效果很好,但是多重继承可以暴露无效的假设。
Base* p = this;
Derived* pDerived = reinterpret_cast<Derived*>(p);