在此示例中,为什么从unique_ptr <derived>到unique_ptr <base>的自动上传失败?

时间:2019-11-10 23:02:11

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

ControllerSender是基类,几个类将是该基类的直接子代(在此示例中仅BasicSender)并通过工厂函数MidiControllers::AddSender实例化。

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

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

  

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

失败的行是

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

1 个答案:

答案 0 :(得分:4)

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

class BasicSender : ControllerSender

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

要修复,请使用public:

class BasicSender : public ControllerSender

(或使用struct而不是class关键字,这意味着默认访问是公共的。)