无法将派生的原始指针分配给基unique_ptr

Cannot assign derived raw pointer to base unique_ptr

提问人:conectionist 提问时间:1/26/2023 最后编辑:Remy Lebeauconectionist 更新时间:1/26/2023 访问量:142

问:

我有一些代码看起来像这样:

class Info {
  public:
    virtual bool IsHere() = 0;
    virtual std::wstring GetStr() = 0;
};

class WindowsInfo : public Info {
  public:
    virtual std::wstring GetAnotherStr() = 0;
    bool IsHere() override;
};

class AdvancedWindowsInfo : public WindowsInfo {
  public:
    AdvancedWindowsInfo() {}
    ~AdvancedWindowsInfo() {}

    std::wstring GetAnotherStr() override;
    std::wstring GetStr() override;
};
  
class InfoFactory {
  public:
    static Info* GetInfo();
};
  
class InfoManager {
  public:
    InfoManager();
    //~InfoManager();

    bool IsSomething();

  private:
    std::unique_ptr<Info> info;
};
  
InfoManager::InfoManager() {
  #if WIN
    info = std::make_unique<WindowsInfo>();
  #else  // currently no implementation Linux
    info = nullptr;
  #endif
}
  
bool InfoManager::IsSomething() {
    std::unique_ptr<Info> info = InfoFactory::GetInfo();

    return info && info->IsHere();
}
  
Info* InfoFactory::GetInfo() {
  #if IS_WINDOWS
    return new AdvancedWindowsInfo();
  #else
    return nullptr;
  #endif
}

整个代码太大(而且是机密的),无法在此处发布,但这个代码片段很好地总结了它。

从本质上讲,我有一个基类和一些派生类。

我还有一个管理器,它使用指向该基类的(智能)指针。

以及返回相应 Derived 对象的 Factory 方法(尽管签名返回 ).Base*

不幸的是,我无法让分配(通过工厂方法)工作。我尝试了多种方法,但没有任何效果。

我尝试使用 和 -->它不适用于派生类,仅适用于基础类。unique_ptrmake_unique<raw pointer>()

我尝试使用原始指针 - >转换是不可能的。unique_ptr

我尝试使用原始指针(尽管我不想要这个)和原始指针 - >它告诉我析构函数是在抽象的基对象上调用的。当你没有实例化对象时,你怎么能调用析构函数(因为它是一个抽象类)?编译器自相矛盾!

C++ 智能指针 虚拟继承

评论

1赞 Galik 1/26/2023
你不能退货吗?那会更值得推荐。InfoFactory::GetInfo()std::unique_ptr<Info>
2赞 François Andrieux 1/26/2023
“不起作用”和“无法正常工作”不是描述性的。是否出现编译器错误?它会崩溃吗?你会得到意想不到的结果吗?如果出现错误,会出现什么错误?
1赞 Avi Berger 1/26/2023
此外,创建一个_local_variable信息,当函数返回时,该信息超出范围。它使成员变量信息不受影响。也许你的意图是std::unique_ptr<Info> info = InfoFactory::GetInfo();info.reset( InfoFactory::GetInfo() );
3赞 Nathan Pierson 1/26/2023
“当你没有实例化对象时,你怎么能调用析构函数......”你给真正的析构函数了吗?你没有给出显示的那个。看这里Infovirtual ~Info() = default;Info

答:

3赞 Nathan Pierson 1/26/2023 #1

让我们检查一下 的构造函数的文档。相关构造函数的签名:std::unique_ptr

explicit unique_ptr( pointer p ) noexcept;(2)

将原始指针转换为 的转换构造函数是 。除其他事项外,这意味着它不能用于表单的复制初始化std::unique_ptrexplicit

std::unique_ptr<Info> info = InfoFactory::GetInfo();

相反,您可以使用直接初始化

std::unique_ptr<Info> info{InfoFactory::GetInfo()};

这将允许您执行该转换。


但是,在查看此代码时,我注意到 中的局部变量隐藏了类成员变量。如果要更改现有指针,以便它现在管理新的原始指针,则可能需要使用 resetinfoInfoManager::IsSomethingInfoManager::infostd::unique_ptr

info.reset(InfoFactory::GetInfo());

评论

0赞 user4581301 1/26/2023
如果你想要转换。安全存储之间存在故障空间,这将通过std::make_unique的端到端curtesy来解决。new AdvancedWindowsInfo();infounique_ptr
0赞 conectionist 1/26/2023 #2

好的,所以我做了以下操作:

  1. InfoFactory::GetInfo()现在返回一个 ,如 Galik 所示std::unique_ptr<Info>
  2. 按照内森·皮尔森(Nathan Pierson)的指示添加virtual ~Info() = default;

现在一切似乎都正常。 现在,我将这个问题悬而未决,因为我仍然需要运行一些测试并仔细检查一些事情,但基本上似乎没问题。

感谢所有做出积极贡献的人!