2016-11-07 21 views
0

クラスIPrinterManagerおよびその子クラスColorPrinterManagerが指定されています。 ColorPrinterは、子クラスのAbstractPrinterです。コンパイルはメッセージ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); 

}; 

答えて

3

std::vector<std::shared_ptr<AbstractPrinter>>*を返す必要があります。その周りに行くことはありません。あなたはまだそれをColorPrinterポインタで入力できます。

仮想関数の戻り値の型として、より多くの派生型を指定できます。しかし、ポインタのvectorにはそのような関係はありません。


また、値を返すことを検討してください。 NRVOと移動セマンティクスを使用すると、ベクトルはリソースを効率的に管理する上で非常に優れています。

+0

しかし、カラープリンタだけを返すようにしたいと考えています。それ以外の方法はありませんか? – user1056903

+1

@ user1056903、あなたの実装はそれを強制する方法であり、クライアントは気にする必要はありません。 'AbstractPrinter'が適切なインターフェースを提供しないためにこれをしたいのであれば、デザインを再考する必要があります。 – StoryTeller

0

ColorPrinterAbstractPrinter由来するかもしれないが、shared_ptr<ColorPrinter>shared_ptr<AbstractPrinter>vector<shared_ptr<ColorPrinter>>に由来するものではないvector<shared_ptr<AbstractPrinter>>に由来するものではありません。したがって、あなたのprint関数は共変量ではありません。

vector<shared_ptr<AbstractPrinter>>とする必要があります。もちろん、あなたが本当にここ共変戻り値の型が必要な場合は、

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

のようなコードがある場合、1つの方法は、プリンタの横のプリンタコンテナの並列階層構造を定義し、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仮想でないことを考えてください。(値で返します)。

関連する問題