【问题标题】:Overriding return type in child class覆盖子类中的返回类型
【发布时间】:2017-03-20 13:52:31
【问题描述】:

给出的是类IPrinterManager 及其子类ColorPrinterManagerColorPrinterAbstractPrinter 的子类。编译中止并显示消息ColorPrinterManager::print is not a covariant of 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);

};

【问题讨论】:

    标签: c++ pointers inheritance polymorphism virtual


    【解决方案1】:

    您需要返回std::vector&lt;std::shared_ptr&lt;AbstractPrinter&gt;&gt;*。没有办法绕过它。您仍然可以通过 ColorPrinter 指针填充它。

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


    另外,考虑按值返回。借助 NRVO 和移动语义,向量非常擅长有效地管理其资源。

    【讨论】:

    • 但我想强制只能退回彩色打印机。没有其他办法吗?
    • @user1056903,您的实施就是您执行的方式,客户不必关心。如果您想这样做是因为 AbstractPrinter 没有提供足够的界面来使用,您需要重新考虑您的设计。
    【解决方案2】:

    ColorPrinter 可能派生自 AbstractPrinter,但 shared_ptr&lt;ColorPrinter&gt; 不是派生自 shared_ptr&lt;AbstractPrinter&gt; 并且 vector&lt;shared_ptr&lt;ColorPrinter&gt;&gt; 不是派生自 vector&lt;shared_ptr&lt;AbstractPrinter&gt;&gt;。所以你的 print 函数不是协变的。

    您需要坚持使用vector&lt;shared_ptr&lt;AbstractPrinter&gt;&gt;。当然,如果你有类似的代码

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

    【讨论】:

      【解决方案3】:

      如果您在这里确实需要协变返回类型,一种方法是在打印机容器旁边定义打印机容器的并行层次结构,并使用它来代替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; ...
      

      注意 1:get 返回常规指针,而不是共享指针。这是因为我们需要它具有协变返回类型,并且它不适用于智能指针。 (有办法绕过它)。

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

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

      注4:这相当麻烦。考虑使print 非虚拟(并按值返回)。

      【讨论】:

        猜你喜欢
        • 2019-06-28
        • 1970-01-01
        • 1970-01-01
        • 2010-11-06
        • 1970-01-01
        • 2013-12-23
        • 2015-04-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多