2017-01-04 13 views
1

仮想メソッドを適切にオーバーライドしています。私はいくつかのコンストラクタを連結し、基本クラスのコンストラクタで私は仮想メソッドを呼び出します。以下のようにC++仮想メソッドが期待通りに呼び出されない

コールチェーンは次のようになります。

B(p)->A(p)->B.foo(p) 

コールチェーンは、C++である:

B(p)->A(p)->A.foo(p) 

コールチェーンは、C#である:他の言葉でそう

B(p)->A(p)->B.foo(p) 

、中C#の動作は期待通りですが、Cではそうではありません。

C++コード:

#include <cstdio> 

class A { 
public: 
    A(); 
    A(int); 

    virtual void foo(int s); 
}; 

class B : public A { 
public: 
    B(); 
    B(int s) : A(s) {}; 

    virtual void foo(int s) override; 
}; 

A::A() { 
    std::printf("A\r\n"); 
}; 

A::A(int s) : A() { 
    std::printf("A: %d\r\n", s); 
    foo(s); 
}; 

void A::foo(int s) { 
    std::printf("A::foo(%d)\r\n", s); 
} 

B::B() : A(){ 
    std::printf("B\r\n"); 
}; 

void B::foo(int s) { 
    std::printf("B::foo(%d)\r\n", s); 
} 

int main(int argc, char* argv[]) { 
    B b(2); 
} 

出力:

A 
A: 2 
A::foo(2) 

C#コード:

using System; 

namespace demo { 
class A{ 
    public A() { 
    Console.WriteLine("A"); 
    } 

    public A(int s) : this(){ 
    Console.WriteLine("A: " + s.ToString()); 
    foo(s); 
    } 

    public virtual void foo(int s) { 
    Console.WriteLine(string.Format("A:foo({0})", s)); 
    } 
} 

class B : A{ 
    public B() : base() { 
    Console.WriteLine("B"); 
    } 

    public B(int s) : base(s) { 
    } 

    public override void foo(int s) { 
    Console.WriteLine(string.Format("B:foo({0})", s)); 
    } 
} 

    static class Run { 
    static void Main() { 
     new B(2); 
    } 
    } 
} 

出力:

A 
A: 2 
B::foo(2) 

クラスBのオーバーライドされたメソッドがC++で呼び出されないのはなぜですか?正しく上書きする必要がありますか?

+5

仮想ディスパッチは、コンストラクタが終了するまで機能しません。 – Arunmu

+1

http://stackoverflow.com/questions/962132/calling-virtual-functions-inside-constructors – tia

+0

あなたはC++とC#の出力が同じだと言いました。 C#でB :: foo(2)を呼び出すのですか? – Zebrafish

答えて

0

これはC++が動作する単なる方法です。仮想関数は、オブジェクトの構築や破壊時にはほとんど動作しません。

+1

なぜですか?彼らは:)、そのちょうど彼らは、著者によって期待されていないvtablesを使用する –

関連する問題