【问题标题】:Why is automatic upcasting from unique_ptr<derived> to unique_ptr<base> failing in this example?为什么在此示例中从 unique_ptr<derived> 自动向上转换为 unique_ptr<base> 失败?
【发布时间】:2019-11-10 23:02:11
【问题描述】:

ControllerSender 是基类,有几个类是它的直接子类(本例中只有 BasicSender)并通过工厂函数 MidiControllers::AddSender 实例化。

指向实例化对象的指针以及其他信息存储在映射中。在 map 中构建信息的顺序是首先使用AddController 获取 key (id),并在 map 中放置一个新成员,默认为 Capabilities。然后AddOutputPtrCapabilities 中放置一个shared_ptr 到输出设备的键。最后AddSender 为从ControllerSender 派生的密钥创建一个新的发送者。失败的正是这第三步。

工厂函数抛出这个编译器错误:

binary '=': 没有找到使用 'std::unique_ptr>' 类型的右侧操作数的运算符(或没有可接受的转换)和 [_Ty=BasicSender ]

失败的线是

controllers_.at(id).sender_ = std::make_unique<BasicSender>(ptr);

如果我将 BasicSender 更改为基类 (ControllerSender),则该行编译不会出错。我认为这个赋值应该自动向上转换指针,如Is unique_ptr<Derived> to unique_ptr<Base> up-casting automatic? 中所述。

我该如何解决这个问题?

#include <map>
#include <vector>
#include <JuceLibraryCode/JuceHeader.h>

class ControllerSender {
 public:
   ControllerSender(std::shared_ptr<juce::MidiOutput>& device) : device_(device) {}

 private:
   std::shared_ptr<juce::MidiOutput> device_{};
};

class BasicSender : ControllerSender {
 public:
   using ControllerSender::ControllerSender;
};

class MidiControllers {
 public:
   void AddController(const juce::MidiDeviceInfo& id)
   {
      controllers_.insert({id, Capabilities{}});
   }
   void AddOutputPtr(const juce::MidiDeviceInfo& id, std::shared_ptr<juce::MidiOutput>& device)
   {
      controllers_.at(id).device_ = device;
   }
   void AddSender(const juce::MidiDeviceInfo& id, std::string sender_name)
   {
      auto& ptr = controllers_.at(id).device_;
      if (ptr) {
         if (sender_name == "BasicSender") {
            controllers_.at(id).sender_ = std::make_unique<BasicSender>(ptr);
         }
      }
   }

 private:
   struct Capabilities {
      std::shared_ptr<juce::MidiOutput> device_{nullptr};
      std::unique_ptr<ControllerSender> sender_{nullptr};
   };

   struct IdentifierComp {
      bool operator()(const juce::MidiDeviceInfo& lhs, const juce::MidiDeviceInfo& rhs) const
          noexcept
      {
         return lhs.name < rhs.name || lhs.identifier < rhs.identifier;
      }
   };
   std::map<juce::MidiDeviceInfo, Capabilities, IdentifierComp> controllers_;
};

【问题讨论】:

  • T 派生自U 时,可以将unique_ptr&lt;T&gt; 分配给unique_ptr&lt;U&gt;。但这确实需要U 有一个虚拟析构函数。您的基类 ControllerSender 没有。另外,您的BasicSender 使用的是私有继承而不是公共继承,这是您真正想要的吗?

标签: c++ c++11 unique-ptr upcasting


【解决方案1】:

问题是你使用了私有继承:

class BasicSender : ControllerSender

这意味着没有从BasicSender *ControllerSender * 的隐式转换,因此相应的智能指针也没有隐式转换。

要修复,请使用 public:

class BasicSender : public ControllerSender

(或使用struct 关键字代替class,这意味着默认访问是公开的)。

【讨论】:

    猜你喜欢
    • 2020-01-30
    • 2018-12-15
    • 2016-07-23
    • 2014-03-27
    • 2019-05-24
    • 2014-07-21
    • 2015-08-08
    • 1970-01-01
    • 2020-07-17
    相关资源
    最近更新 更多