2011-01-17 3 views
2

私はそれが派生オブジェクトに対して呼び出されたとき、それはDescendant.Iを返すことのようにDeriveds fooのを書きたいが、これは共変戻り値の型の使用を簡単に行うことができることを知っています。しかし、もし私がこの機能を使うことができなかったらどうしますか?どのように私は上記のコードでこの機能をシミュレートできますか?シミュレート共変戻り値の型の挙動

+2

...とにかく '派生:: foo'のための共変戻り値を持つことができませんでした。実行時の多態性は、ポインタまたは参照と仮想ディスパッチを介して機能します。あなたの本当の問題を知らずに、あなたに何が役に立つかを知るのは難しいです。例えば、祖先への参照やポインタを返すことができますか? –

+0

はいできます。私の質問は、 "共変な戻り値の型をサポートしていないコンパイラ(古いもののような)でこの問題を解決するにはどうすればいいですか" – thikonom

答えて

2
Ancestor * Derived::foo 
{ 
// Do whatever 
    return new Descendant (); 
} 

ポインタを使用できる場合は、アップキャストされたDecendポインタを返します。返されたポインタはDescendantを指し、メソッドが仮想であると仮定すると、同様にDescendentのように動作します。

+2

はい - ここでの重要な点は、この単純な文書の明示的な文書として共変の戻り値型が追加されたことです(より多くのコンパイラチェック、APIのより有益な戻り型、可能性のある追加の最適化を可能にする) - 多型は、共変リターン型が導入される前にうまく動作し、下位互換性を保持します。 –

3

派生オブジェクトのために呼び出されたときにDescendantを返すように、派生クラスfooを記述します。 fooので

// Do not redefine foo as : Descendant foo(void); 

値によってAncestorを返して、達成する唯一の方法(の限られた種類の)共分散fooを再定義することです。したがって、の要件は矛盾しているです。

C++は、共変量生ポインタと生の参照結果をサポートします。 boost::shared_ptrstd::auto_ptrなどのスマートポインタの結果型では、派生クラスでpublic関数を再定義することによって共分散を実装する必要があります。これはあなたの問題に似ています。なぜなら、共分散関数は生ポインタまたは生の参照ではなく–の値を返すからです。–しかし、’もあなたの問題と異なります。スマートポインタのタイプ間に継承関係はありません。 。ここ

は例です:二つの第一foo

#include <memory> 
#include <typeinfo> 
using namespace std; 

struct Ancestor{ virtual ~Ancestor(){} }; 
struct Descendant : Ancestor {}; 

class Base 
{ 
protected: 
    virtual Ancestor* virtualFoo() const 
    { 
     return new Ancestor(); 
    } 

public: 
    auto_ptr<Ancestor> foo() const 
    { 
     return auto_ptr<Ancestor>(virtualFoo()); 
    } 
}; 

class Derived : public Base 
{ 
protected: 
    virtual Descendant* virtualFoo() const 
    { 
     return new Descendant(); 
    } 

public: 
    auto_ptr<Descendant> foo() const 
    { 
     return auto_ptr<Descendant>(virtualFoo()); 
    } 
}; 

#include <iostream> 

int main() 
{ 
    Base baseObject; 
    Derived derivedObject; 
    Base& baseRef  = derivedObject; 

    cout << typeid(*baseObject.foo()).name() << endl; 
    cout << typeid(*derivedObject.foo()).name() << endl; 
    cout << typeid(*baseRef.foo()).name() << endl; 
} 

は、静的結果タイプは、共分散は、すべて使用してコード’の視点から約あるものであるダイナミック型、に対応する呼び出し。

指示先オブジェクトタイプ​​であるが、最後のfoo呼び出しでfoo結果の静的タイプは、std::auto_ptr<Ancestor>あります。

仮想関数のオーバーライドは、C++ ’のrawポインタ型の共変結果の組み込みサポートに依存します。

乾杯& HTH。、 `基本::値で` Ancestor`を返しfoo`として