2012-06-03 5 views
7

以下のコードの結果が "クラスB :: 1"になる理由を説明できますか?コードは派生クラスメソッドを実行しますが、基底クラスメソッドからデフォルトパラメータを取得します

派生クラスの仮想メソッドは、自分自身ではなく、基本クラスのデフォルトパラメータを使用するのはなぜですか?私にとってこれはかなり奇妙です。前もって感謝します!

コード:

#include <iostream> 

using namespace std; 

class A 
{ 
public: 
    virtual void func(int a = 1) 
    { 
     cout << "class A::" << a; 
    } 
}; 

class B : public A 
{ 
public: 
    virtual void func(int a = 2) 
    { 
     cout << "class B::" << a; 
    } 
}; 

int main() 
{ 
    A * a = new B; 
    a->func(); 

    return 0; 
} 

答えて

6

デフォルトの引数は静的型this(つまり、A&のような変数自体のタイプはA& a;です)。

少しあなたの例を変更:

#include <iostream> 

class A 
{ 
public: 
    virtual void func(int a = 1) 
    { 
     std::cout << "class A::" << a << "\n"; 
    } 
}; 

class B : public A 
{ 
public: 
    virtual void func(int a = 2) 
    { 
     std::cout << "class B::" << a << "\n"; 
    } 
}; 

void func(A& a) { a.func(); } 

int main() 
{ 
    B b; 
    func(b); 
    b.func(); 

    return 0; 
} 

我々は次の出力を観察:アクションで

class B::1 
class B::2 

ideoneで。

仮想関数がこのような理由でデフォルト値を変更することはお勧めしません。残念ながら、私はこのコンストラクトを警告するコンパイラは知らない。

  • がトランポリンとして機能する新しい関数を作成します:


    技術的な解説は、デフォルトの引数を扱う2つの方法があるということですvoid A::func() { func(1); }

  • アドインの呼び出しで引数がありませんサイトa.func() =>a.func(/*magic*/1)

それはA::funcワット、前者(と仮定した場合virtualと同様に宣言されています)、期待どおりに動作します。しかし、virtualの問題が当時予期されていなかったか、(もしあれば...)利益の面で重要ではないと考えられたために、後者の形式が選出された。

5

(::のFUNC又はB :: FUNC)呼び出される実際の関数は、実行時に決定されるデフォルト値は、コンパイル時に置換されていると宣言から取られるからです。

+0

ありがとうございました! – Aremyst

5

C++での多態性は実行時に有効になりますが、デフォルトパラメータの置換はコンパイル時に有効になるためです。コンパイル時に、コンパイラは、ポインタaが指し示すオブジェクトの動的型を知らない(そしてそれを知っているとは思わない)。したがって、それはaのために知っている唯一の型のデフォルト引数をとります。あなたの例ではA *です。

(これは、偶然にも、デフォルトのパラメータが実装/定義のインターフェイス/ヘッダーはなく、に記載されている理由である。コンパイラは実装のマシンコードのデフォルトのパラメータを挿入していないが、唯一発呼者マシンコードでない。技術的にデフォルトのパラメータは呼び出し側のプロパティであり、呼び出し側はオブジェクトの動的型を知らないので、オブジェクトの動的な型を知らなくてもよい)。

+0

あなたの答えは非常に明確です、ありがとう! – Aremyst

関連する問題