为什么在此示例中从 unique_ptr<derived> 自动向上转换到 unique_ptr<base> 失败?
Why is automatic upcasting from unique_ptr<derived> to unique_ptr<base> failing in this example?
ControllerSender
是基础 class,几个 classes 将是它的直接子代(本例中只有 BasicSender
)并通过工厂实例化函数 MidiControllers::AddSender
.
指向实例化对象的指针以及其他信息存储在映射中。在地图中构建信息的顺序是首先使用 AddController
获取密钥 (id),并在默认 Capabilities
的地图中放置一个新成员。然后 AddOutputPtr
在 Capabilities
中为该键放置一个 shared_ptr
到输出设备。最后 AddSender
为从 ControllerSender
派生的密钥创建了一个新的发件人。这是失败的第三步。
工厂函数抛出这个编译器错误:
binary '=': no operator found which takes a right-hand operand of type 'std::unique_ptr<BasicSender,std::default_delete<_Ty>>' (or there is no acceptable conversion) with [_Ty=BasicSender]
失败的行是
controllers_.at(id).sender_ = std::make_unique<BasicSender>(ptr);
如果我将 BasicSender
更改为基础 class (ControllerSender
),则该行编译没有错误。我认为这个赋值应该自动向上转换指针,如 .
中所述
我该如何解决这个问题?
#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_;
};
问题是你使用了私有继承:
class BasicSender : ControllerSender
表示没有从BasicSender *
到ControllerSender *
的隐式转换,因此对应的智能指针也没有隐式转换。
要修复,请使用 public:
class BasicSender : public ControllerSender
(或使用 struct
关键字而不是 class
,这意味着默认访问权限是 public)。
ControllerSender
是基础 class,几个 classes 将是它的直接子代(本例中只有 BasicSender
)并通过工厂实例化函数 MidiControllers::AddSender
.
指向实例化对象的指针以及其他信息存储在映射中。在地图中构建信息的顺序是首先使用 AddController
获取密钥 (id),并在默认 Capabilities
的地图中放置一个新成员。然后 AddOutputPtr
在 Capabilities
中为该键放置一个 shared_ptr
到输出设备。最后 AddSender
为从 ControllerSender
派生的密钥创建了一个新的发件人。这是失败的第三步。
工厂函数抛出这个编译器错误:
binary '=': no operator found which takes a right-hand operand of type 'std::unique_ptr<BasicSender,std::default_delete<_Ty>>' (or there is no acceptable conversion) with [_Ty=BasicSender]
失败的行是
controllers_.at(id).sender_ = std::make_unique<BasicSender>(ptr);
如果我将 BasicSender
更改为基础 class (ControllerSender
),则该行编译没有错误。我认为这个赋值应该自动向上转换指针,如
我该如何解决这个问题?
#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_;
};
问题是你使用了私有继承:
class BasicSender : ControllerSender
表示没有从BasicSender *
到ControllerSender *
的隐式转换,因此对应的智能指针也没有隐式转换。
要修复,请使用 public:
class BasicSender : public ControllerSender
(或使用 struct
关键字而不是 class
,这意味着默认访问权限是 public)。