2016-05-25 1 views
0

をマッチング:C++多型の機能私は仮想関数とチェーンの継承とコード怒鳴るを持っており、それが印刷さ

D ptr 
E 

だから、機能マッチングのためのアルゴリズムは何である、私の推測では、それが最も近い父クラスを一致だのですか?しかし、& eは基本的にA *、B *、D *型です。なぜこれもコンパイルされ、このプロパティを使うのは良い習慣ですか?

#include <iostream> 

using namespace std; 

class A { 
    public: 
     virtual void f(){cout<<"A";}; 
}; 

class B :public A { 
    public: 
    virtual void f() { 
     cout<<"B"; 
    } 
}; 

class D : public B { 
    public: 
    virtual void f() { 
     cout<<"D"; 
    } 
}; 

class E : public D { 
    public: 
    virtual void f() { 
     cout<<"E"; 
    } 
}; 

void f(D *sth) { 
    cout<<"D ptr"<<endl; 
    sth->f(); 
} 

void f(B *sth) { 
    cout<<"B ptr"<<endl; 
    sth->f(); 
} 

void f(A *sth) { 
    cout<<"A ptr"<<endl; 
    sth->f(); 
} 

int main() { 
    E e; 
    f(&e); 
} 
+0

ここでは、2つの質問があります.1つはオーバーロードの解決と継承の連鎖です。 –

+0

なぜ 'E'を印刷するのか理解していますか? –

+0

グローバルf関数の複数のオーバーロードを持つことは、選択が実際の型ではなく宣言された型に依存するため、一般的には良い考えではありません。 – Phil1970

答えて

0

私は私ができるよう最善のようにあなたの例を打破しようとします:十分

int main() { 
    E e; // declare object of Class E 
    f(&e); // run f() function and pass it the address of E 
} 

[OK]を、単純な - あなたは、クラスEのオブジェクトを宣言し、それに機能を実行しました。グローバルf()関数は、Dオブジェクト、Bオブジェクト、またはAオブジェクトのアドレスへのポインタを受け入れるために3回オーバーロードされました。これらのすべてが継承ツリー上でオブジェクトを上位に取るので、いずれもクラスEオブジェクトで動作します。コンパイラは、最も派生したクラスの関数を選択します。この場合、void f(D * sth)関数が選択されます。 Eが印刷されますなぜ

void f(D *sth) { 
    cout<<"D ptr"<<endl; // "D ptr" printed to screen 
    sth->f();   // Take original pointer to class E object and 
         // run its own class method f() on it 
} 

は、次にEのクラス定義を見て、我々が表示されます:

class E : public D { 
    public: 
    virtual void f() { 
     cout<<"E"; 
    } 
}; 

あなたはボイドF(D * STH)関数をコメントアウトした場合、コンパイラを希望代わりにvoid f(B * sth)関数を選択して、結果として "B ptr"と "E"を出力します。代わりにAとBオブジェクトのグローバルf()関数をコメントアウトし、Bオブジェクトでvoid f(D * sth)を実行しようとすると、コンパイラはオブジェクトを継承ツリー、それをダウンではありません。

Phil1970がコメントしたように、この構造は一般的には継承ツリーの知識を持つグローバル関数に依存しているため、戸惑うことがあります。

0

未定義の動作やあいまいさがあるはずです。コンパイラのバージョンが異なると結果が変わる可能性があります。

関連する問題