【问题标题】:Cannot assign derived raw pointer to base unique_ptr无法将派生的原始指针分配给基 unique_ptr
【发布时间】:2023-01-26 02:15:46
【问题描述】:

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

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

整个代码太大(且机密)无法发布在这里,但是这个 sn-p 总结得很好。
本质上,我有一个基类和一些派生类。
我还有一个使用指向该基类的(智能)指针的管理器。
以及一个返回适当派生对象的工厂方法(尽管签名返回一个 Base*)。

不幸的是,我无法让分配(通过工厂方法)工作。
我尝试了多种方法,但没有任何效果。
我尝试使用 unique_ptr 和 make_unique() --> 它不适用于派生类,仅适用于基类。
我尝试使用 unique_ptr 和原始指针 --> 转换是不可能的。
我尝试使用原始指针(虽然我不想要这个)和原始指针 --> 它告诉我析构函数是在抽象的基础对象上调用的。当你没有实例化对象(因为它是一个抽象类)时,你怎么能调用析构函数?编译器自相矛盾!

非常欢迎任何点击、想法或帮助!

谢谢!

【问题讨论】:

  • 你不能让 InfoFactory::GetInfo() 返回 std::unique_ptr&lt;Info&gt; 吗?那会更推荐。
  • “不起作用”和“无法使其工作”不是描述性的。你有编译错误吗?它会崩溃吗?你会得到意想不到的结果吗?如果你得到一个错误,你会得到什么错误?
  • 此外,std::unique_ptr&lt;Info&gt; info = InfoFactory::GetInfo(); 创建了一个 _local_variable 信息,该信息在函数返回时超出范围。它使成员变量信息不受影响。也许你想要的是info.reset( InfoFactory::GetInfo() );

标签: c++ pointers inheritance smart-pointers virtual-inheritance


【解决方案1】:

让我们查看std::unique_ptrconstructors 的文档。相关构造函数的签名:

explicit unique_ptr( pointer p ) noexcept; (2)

将原始指针转换为 std::unique_ptr 的转换构造函数是 explicit。除其他外,这意味着它不能用于表单的copy initialization

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

相反,您可以使用direct initialization

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

这将允许您执行该转换。


然而,在查看这段代码时,我注意到 InfoManager::IsSomething 中的局部变量 info 隐藏了类成员变量 InfoManager::info。如果你想改变现有的std::unique_ptr,让它现在管理一个新的原始指针,你可能想使用reset

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

【讨论】:

  • 如果你想要转换。 new AdvancedWindowsInfo();info 中的安全存储之间存在故障空间,可以通过std::make_unique 的端到端unique_ptr 或中间 std::shared_ptr 解决,如果您认为工厂的额外多功能性一个好主意。
猜你喜欢
  • 1970-01-01
  • 2021-09-09
  • 2017-08-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-03-04
相关资源
最近更新 更多