C++ 重写子类中的返回类型

C++ 重写子类中的返回类型,c++,pointers,inheritance,polymorphism,virtual,C++,Pointers,Inheritance,Polymorphism,Virtual,给定的是类IPrinterManager及其子类ColorPrinterManagerColorPrinter是AbstractPrinter的子类。编译中止,并显示以下消息:ColorPrinterManager::print不是IPrinterManager::print的协变项。如何解决此问题 class IPrinterManager { public: virtual std::vector<std::shared_ptr<AbstractPrinter>&g

给定的是类
IPrinterManager
及其子类
ColorPrinterManager
ColorPrinter
AbstractPrinter
的子类。编译中止,并显示以下消息:ColorPrinterManager::print不是IPrinterManager::print的协变项。如何解决此问题

class IPrinterManager
{
public:

   virtual std::vector<std::shared_ptr<AbstractPrinter>>* print(std::string text) = 0;

};

class ColorPrinterManager : public IPrinterManager
{
public:

   std::vector<std::shared_ptr<ColorPrinter>>* print(std::string text);

};
类IPrinterManager
{
公众:
虚拟标准::矢量*打印(标准::字符串文本)=0;
};
类ColorPrinterManager:公共IPrinterManager
{
公众:
标准::矢量*打印(标准::字符串文本);
};

您需要返回
std::vector*
。这是不可能的。您仍然可以通过
彩色打印机
指针来填充它

协变返回类型允许您指定更派生的类型,作为虚拟函数的返回类型。但是
vector
s指针没有这样的关系



也可以考虑按价值返回。使用NRVO和move语义,vectors非常擅长有效地管理其资源。

您需要返回
std::vector*
。这是不可能的。您仍然可以通过
彩色打印机
指针来填充它

协变返回类型允许您指定更派生的类型,作为虚拟函数的返回类型。但是
vector
s指针没有这样的关系



也可以考虑按价值返回。有了NRVO和move语义,vector真的很擅长有效地管理它们的资源。

ColorPrinter
可能源于
AbstractPrinter
,但
shared\u ptr
不是源于
shared\u ptr
vector
不是源于
vector
。因此,您的
打印
函数不是协变函数

您需要坚持使用
vector
。当然,如果你有这样的代码

ColorPrinterManager pm;
auto v = pm.print(string("bla"));
for(auto &s : v) {
    // This gives you the AbstractPrinter
    auto p = s.get();
    // If you called ColorPrinterManager you know that all printers are ColorPrinter
    auto p2 = dynamic_cast<ColorPrinter*>(p);
}
ColorPrinterManager pm;
自动v=pm.print(字符串(“bla”);
用于(自动和s:v){
//这将为您提供抽象打印机
自动p=s.get();
//如果调用ColorPrinterManager,您知道所有打印机都是ColorPrinter
自动p2=动态施法(p);
}

彩色打印机
可以从
抽象打印机
派生,但是
共享的ptr
不是从
共享的ptr
派生的,
向量
不是从
向量
派生的。因此,您的
打印
函数不是协变函数

您需要坚持使用
vector
。当然,如果你有这样的代码

ColorPrinterManager pm;
auto v = pm.print(string("bla"));
for(auto &s : v) {
    // This gives you the AbstractPrinter
    auto p = s.get();
    // If you called ColorPrinterManager you know that all printers are ColorPrinter
    auto p2 = dynamic_cast<ColorPrinter*>(p);
}
ColorPrinterManager pm;
自动v=pm.print(字符串(“bla”);
用于(自动和s:v){
//这将为您提供抽象打印机
自动p=s.get();
//如果调用ColorPrinterManager,您知道所有打印机都是ColorPrinter
自动p2=动态施法(p);
}

如果您确实需要协变返回类型,一种方法是在打印机容器的旁边定义打印机容器的并行层次结构,并使用它代替
std::vector

// printers
class AbstractPrinter { ...

class ColourPrinter : public AbstractPrinter { ...

// printer collections
class AbstractPrinterCollection {
      public: virtual AbstractPrinter* get(int i) = 0; ...

class ColourPrinterCollection : public AbstractPrinterCollection {
      public: ColourPrinter* get(int i) override { ... }
      private: std::vector<std::shared_ptr<ColourPrinter>> vec; ...
//打印机
类抽象打印机{。。。
类彩色打印机:公共抽象打印机{。。。
//打印机集
类AbstractPrinterCollection{
公共:虚拟抽象打印机*get(int i)=0。。。
类ColorPrinterCollection:公共抽象PrinterCollection{
公共:彩色打印机*获取(int i)覆盖{…}
私有:std::vector vec。。。
注1:
get
返回一个常规指针,而不是共享指针。这是因为我们需要它具有协变返回类型,并且它不适用于智能指针(有很多方法可以解决)

注2:只有整个层次结构中的叶类才有数据成员(就像带有实际打印机的实际容器),基类和中间类将数据委托给叶,并且可能是完全抽象的

注3:AbstractPrinterCollection中没有
put
(叶类中可能有
put


注4:这是相当麻烦的。考虑制作<代码>打印< /COD>非虚(和按值返回)。

< P>如果这里真的需要协变返回类型,一种方法是定义打印机容器的并行层次结构,而不是打印机,使用它代替<代码> STD::向量< /代码> .<
// printers
class AbstractPrinter { ...

class ColourPrinter : public AbstractPrinter { ...

// printer collections
class AbstractPrinterCollection {
      public: virtual AbstractPrinter* get(int i) = 0; ...

class ColourPrinterCollection : public AbstractPrinterCollection {
      public: ColourPrinter* get(int i) override { ... }
      private: std::vector<std::shared_ptr<ColourPrinter>> vec; ...
//打印机
类抽象打印机{。。。
类彩色打印机:公共抽象打印机{。。。
//打印机集
类AbstractPrinterCollection{
公共:虚拟抽象打印机*get(int i)=0。。。
类ColorPrinterCollection:公共抽象PrinterCollection{
公共:彩色打印机*获取(int i)覆盖{…}
私有:std::vector vec。。。
注1:
get
返回一个常规指针,而不是共享指针。这是因为我们需要它具有协变返回类型,并且它不适用于智能指针(有很多方法可以解决)

注2:只有整个层次结构中的叶类才有数据成员(就像带有实际打印机的实际容器),基类和中间类将数据委托给叶,并且可能是完全抽象的

注3:AbstractPrinterCollection中没有
put
(叶类中可能有
put


注4:这是相当麻烦的。考虑制作<代码>打印< /COD>非虚(并按值返回).

但我想强制执行只能返回彩色打印机。没有其他方法可以这样做吗?@user1056903,您的实现就是如何强制执行的,客户不必在意。如果您想这样做是因为
AbstractPrinter
没有提供足够的接口来使用,您需要重新考虑您的设计。但我不想这样做o强制只返回彩色打印机。没有其他方法吗?@user1056903,您的实现就是强制执行的方式,客户不必在意。如果您想这样做是因为
AbstractPrinter
没有提供足够的接口来使用,您需要重新考虑您的设计。