2012-05-10 17 views
1

編集はサンプルプログラムとして解くと転載仮想関数は

次のようなシナリオは:

クラス階層:

class Base 
{ 
public: 
    virtual void output() = 0; 
private: 
    int a; 
}; 

class Derived_1 : public Base 
{ 
public: 
    virtual void output() 
    { 
     cout << "Derived_1" << endl; 
    } 
}; 

class Derived_2 : public Derived_1 
{ 
public: 
    virtual void output() 
    { 
     cout << "Derived_2" << endl; 
    } 
}; 

実装:

Derived_2* obj = reinterpret_cast<Derived_2*>(new Derived_1()); 
obj->output(); 

"Derived_2"ではなく "Derived_1"を出力します。私はこれがほとんどあなたにとって新しいことではないと確信していますが、私のアプリケーションで私の工場の機能のいくつかを作ったときに考えなかったものでした。

+7

'derived_2'は' derived_1'から継承してはいけませんか? 'Base'から' derived_1'ですか?それは単にタイプミスですか? – amit

+2

コードの重要な部分が欠落しているようです。たとえば、derived_1はBaseから派生していますか(また、base、rightを意味します)。 derived_2はderived_1から派生していますか?ベース? –

+2

私は、あなたの例ではderived_2は何からも派生していないと誤解していますか?派生したものは何も得られません。 –

答えて

3

Value_object_uint32ではなく、Value_object_dataオブジェクトを割り当てています。 Value_object_uint32としてキャストしているということは何も変わりません。実際のオブジェクトの仮想テーブルには、Value_object_uint32の知識はありません。エラー時に構築された仮想関数テーブルでは、formatValue_object_dataformatを指しています。ストロングアーミングは、実際のオブジェクトを指すポインタのタイプは、状況を修正するために何もしません。

与えられた階層内のすべての基本および継承クラスのコンストラクタは、最も派生したものからルートに、各クラスに対して正確に1回呼び出されます。つまり、基本クラスのコンストラクタを明示的に呼び出す必要はありません。自動的に呼び出されます。あなたはあまりにもそれを行うことができます使用する必要があるいくつかの基本クラスのコンストラクタのかを指定する必要がある場合:もちろん

class Base 
{ 
public: 
    Base() {} // default constructor 
    Base(int a) {} 
}; 

class Derived 
{ 
public: 
    Derived() : Base() 
    { 
    } 

    Derived(int a) 
     : Base(a) // Select the Base ctor that takes an int, instead of the default 
    { 
    } 
}; 

int main() 
{ 
    Derived d1; // Calls Derived() and Base() ctors in this order 
    Derived d2(5); // Calls Derived(5) and Base(5) in this order 
} 

Derived(int a)コンストラクタがBase(int)コンストラクタを呼び出すために必要とされていません。この場合、Base()コンストラクタが自動的に呼び出されます。

+0

実際のコードではなくサンプルの問題を既に再投稿しました。理解しやすいと思ったからです。申し訳ありませんが、あなたの答えは理にかなっていないようです。 – Ian

+0

@Ianそれは大丈夫です、改訂履歴は、見て分かりやすい人のためにあります。 – irobot

3

EDITこの回答は、投稿された元のコードに基づいています。 OPは、切り詰められた例が期待どおりに機能しているのを見てからコードサンプルを更新しました。


あなたのコードは正確に正しいではありませんが、これを実現するような何かのための最も一般的な理由は、あなたが上書きしようとしましたが、あなたの代わりに過負荷を作成したときに正確に正しい署名を取得していないということです。基本クラスを呼び出しても、それは正しく定義されたクラスを呼び出します。

シグネチャの問題のすべてはよくある間違いですが、メソッドのconstanceはシグネチャの一部です。

+0

さて、私は見続けるでしょう。ほとんどの場合、テンプレートで問題が発生していないことを確認したかったのです。 – Ian

+0

ここにコードを貼り付けました。http://codepad.org/faJmyhKSと固定構文エラーです。できます。 –

+0

投稿していただきありがとうございますが、上記の切り捨てバージョンを投稿した実際のコードとサンプルコードがどのように違うのか分かりません。 – Ian

0

少なくとも、new_VO_data()メソッドは壊れています。これは、可変の仮想テーブル・サイズと可変長のパディングのために動作する場合と動作しない場合があります。これらは標準では任意であり、コンパイラ・オプションに依存します。簡単に言えば、動作は未定義です。