Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/design-patterns/2.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++11 从需要通过std::shared\u ptr<;的对象启用\u shared\u的两步构造;自我>;到构造函数中创建的子级_C++11_Design Patterns_Smart Pointers - Fatal编程技术网

C++11 从需要通过std::shared\u ptr<;的对象启用\u shared\u的两步构造;自我>;到构造函数中创建的子级

C++11 从需要通过std::shared\u ptr<;的对象启用\u shared\u的两步构造;自我>;到构造函数中创建的子级,c++11,design-patterns,smart-pointers,C++11,Design Patterns,Smart Pointers,我知道额外的初始化方法是有害的,因为它们为对象的半构造留下了一个非常糟糕的选项,因此所有方法都需要检查这一点。但是这种情况呢 class config; class cfg_item final { private: friend class config; cfg_item(std::weak_ptr<config> owner) : owner(owner) { } std::weak_ptr<config> o

我知道额外的初始化方法是有害的,因为它们为对象的半构造留下了一个非常糟糕的选项,因此所有方法都需要检查这一点。但是这种情况呢

class config;
class cfg_item final
{
    private:
        friend class config;
        cfg_item(std::weak_ptr<config> owner) : owner(owner) { }
        std::weak_ptr<config> owner;
}
class config final : private std::enable_shared_from_this<config>
{
    public:
        config()
        {
             items.emplace(std::make_shared<cfg_item>(weak_from_this())); // Will crash!
        }
    private:
        std::vector<std::shared_ptr<cfg_item>> items;
}
int main(int argc, char * argv[])
{
    std::shared_ptr<config> cfg = std::make_shared<config>();
}
类配置;
类别cfg_最终项目
{
私人:
好友类配置;
cfg_项目(标准::弱_ptr所有者):所有者(所有者){}
std::弱ptr所有者;
}
class config final:private std::从\u中启用\u共享\u
{
公众:
config()
{
items.emplace(std::make_shared(弱_from_this());//将崩溃!
}
私人:
向量项;
}
int main(int argc,char*argv[])
{
std::shared_ptr cfg=std::make_shared();
}
我知道它为什么会崩溃。main中的
std::shared_ptr
尚未使用指向配置实例的共享指针初始化,因此,构造函数不知道如何从这个生成
weak_,只会引发
std::bad_-weak_-ptr
异常,因为在构造函数调用时没有有效的
std::shared_-ptr
指向这个

问题是:我怎样才能避免整个事情?我相信我看到的唯一方法是添加单独的初始化方法,正如我已经提到的那样,这是一种邪恶的方法


关于真实代码的注意事项:构造函数从外部源加载
cfg\u项
。假设所有的
cfg\u项在
config
的整个生命周期内都可用。返回到
config
的弱指针是强制性的,因为
cfg\u项
必须将对其所做的所有更改推回到
config
以保存到外部源

如果您查看的答案,有很强的理由说明为什么需要外部初始化函数。然而,你写得对

我知道额外的初始化方法是有害的,因为它们为对象的半构造留下了一个非常糟糕的选项,因此所有方法都需要检查这一点

有可能减少这个问题。假设您有一个类
foo
,其协议是每次构造
foo
对象时,都需要调用
foo::init()。显然,这是一个脆弱的类(客户端代码最终将省略对
init()
的调用)

因此,一种方法是使
foo
的(非复制/非移动)构造函数成为私有的,并创建一个创建对象的可变静态工厂方法,然后调用
init()


请注意,如果没有此方法,就不可能创建对象,接口甚至不包含
init

您的答案很好,但我在描述中遗漏了一件重要的事情-
config
类是通过boost dependency injector注入的,我无法控制
config
分配。特别是,我不能将其移动到工厂方法。这个答案:听起来是正确的,但是我的
cfg_项
可能会比
config
更长寿,所以我不能只使用原始指针:-(@PiotrK这确实让它更难,那就最好了。你可以嵌入一个非所有权的
config
引用(比如
config&
std::reference\u包装器
)而不是类
cfg\u项中的
weak\u ptr
。它应该是安全的,因为逻辑上
owner
不会比
config
对象活得更长,除非你做了一些非常疯狂的事情。@FrankHB这实际上是我三年前错过的一个非常好的主意。谢谢!
#include <utility>

class foo { 
private:
    foo() {}
    foo(int) {}
    void init() {}

public:
    template<typename ...Args>
    static foo create(Args &&...args) {
        foo f{std::forward<Args>(args)...};
        f.init();
        return f;
    }
};
    template<typename ...Args>
    static foo create(Args &&...args) {
        foo f{std::forward<Args>(args)...};
        f.init();
        return f;
    }
int main() {
    auto f0 = foo::create();
    auto f1 = foo::create(2);
    // Next line doesn't compile if uncommented
    // foo f2; 
}