Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/html/90.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 从std::enable_shared_和抽象基类派生出来可以吗?_C++_Smart Pointers - Fatal编程技术网

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);