2009-08-10 23 views
1

私は期待通りに次のコードが機能しなかったことに少し驚いた:値を返すとき戻り値に仮想関数を使用できますか?

#include "stdio.h" 

class RetA 
{ 
public: 
    virtual void PrintMe() { printf ("Return class A\n"); } 
}; 

class A 
{ 
public: 
    virtual RetA GetValue() { return RetA(); } 
}; 

class RetB : public RetA 
{ 
public: 
    virtual void PrintMe() { printf ("Return class B\n"); } 
}; 

class B : public A 
{ 
public: 
    virtual RetA GetValue() { return RetB(); } 
}; 

int main (int argc, char *argv[]) 
{ 
    A instance_A; 
    B instance_B; 
    RetA ret; 

    printf ("Test instance A: "); 
    ret = instance_A.GetValue(); 
    ret.PrintMe(); // Expected result: "Return class A" 

    printf ("Test instance B: "); 
    ret = instance_B.GetValue(); 
    ret.PrintMe(); // Expected result: "Return class B" 

    return 0; 
} 

ので、仮想メソッドは動作しませんか?私はヒープ上でリターンクラスを割り当てることに戻すべきでしょうか、それとも良い方法がありますか?

(現実には、私はクラスに応じて異なるイテレータ・クラスのインスタンスを返すために、コンテナクラスを継承し、いくつかの異なるクラスをできるように、これを行うにしたい...)

+0

私もC/C++には新しくありませんが、Cでクラスを持つことは許可されていますか?stdio.hとprintfがあるのでC言語で作業しているようです。 C++を使用している場合、C-ish printfとC++ - ish-cout AFAIKを混ぜるのは良い考えではありませんが、私は完全にはわかりません。私はこれについて他の人たちからもっと知りたいと思っています。 –

+1

あなたが何をしているのか分かっていれば、もちろんCとC++を混在させるのは問題ではありません –

答えて

17

多態的な振る舞いは値では機能しません。この動作のためにポインタまたは参照を返す必要があります。

値を返した場合は、オブジェクトの親部分だけが返されることを意味する「スライス」と呼ばれるものが得られます。親オブジェクトに子オブジェクトを正常にストライピングしました。これは安全ではありませんすべて。

を見てください:あなたがいない場合は、ポインタを返すか、

virtual RetA GetValue() { return RetB(); } 

に対処する必要が What is object slicing?

0

はダイナミックオーバーロードを取得しています、あなたが持っている必要がありますダイナミックタイプの異なる静的タイプ。あなたはここにいません。値の代わりに参照またはポインタを返す(そしてライブタイムに注意を払う)。

0

仮想ポインタまたはタイプの参照の宣言に適用可能であり、だからコード変更:仮想RETA &のGetValue()または仮想RETA * GetValueメソッドを()、 しかし、あなたは仮想ではない発行 - あなたは「セマンティックコピー」を使用。

0

を、どのようなあなたはGetValueメソッドから取得することはありませんRETA RETBです。

0

すでに述べた「スライシング」問題の他に、PrintMeメソッドも仮想でなければなりません。

struct B 
{ 
    void print1() const { std::cout << "B" << std::endl; } 
    virtual void print2() const { print1(); } 
}; 
struct D : public B 
{ 
    void print1() const { std::cout << "D" << std::endl; } 
    virtual void print2() const { print1(); } 
}; 
B& f() 
{ 
    static D d; 
    return d; // the object returned is in fact a D, not a B 
} 
int main(){ 
    f().print1(); // B: calling a non-virtual method from a B reference 
    f().print2(); // D: the method is virtual will exec B::print2 
} 
+0

もちろん、実際に私のテストでは、私のポストのちょうど打ち間違いだった。 – Jonatan

関連する問題