3

このコードの出力は15です。なぜ私は本当にその理由がわかりません。私はそれがfoo機能のx=5を使用すると思うが、私は理由を知らない。誰でも助けてくれますか?デフォルトの引数を持つ仮想関数、奇妙な出力

#include <iostream> 
#include <string> 

using namespace std; 


struct A 
{ 
    virtual int foo(int x = 5) 
    { 
     return x*2; 
    } 
}; 

struct B : public A 
{ 
    int foo(int x = 10) 
    { 
     return x*3; 
    } 
}; 



int main(int argc, char** argv) 
{ 
    A* a = new B; 
    cout << a->foo(); 
    return 0; 
} 
+1

[仮想関数のデフォルトの引数の動作]の重複が考えられます(http://stackoverflow.com/questions/6464404/virtual-function-default-arguments-behaviour) – cpplearner

答えて

6

私はそれがfoo機能でx=5を使用していますが、私はなぜ知らないと思います。あなたは静的な型A*を持つオブジェクトにfoo()を呼んでいるので、

基底クラスからはい、デフォルト引数Aの宣言(すなわち5)は、ここで使用されます。 default argumentsは、動的タイプ以外の静的タイプに基づいて決定されます。

標準はこれについて明確な説明、$8.3.6/10 Default arguments [dcl.fct.default]があります

(強調鉱山)

仮想関数呼び出し([class.virtual])は、デフォルトの引数を使用しています によって決定された仮想関数の宣言にstatic オブジェクトを示すポインタまたは参照のタイプ。派生クラスのオーバーライド 関数は、オーバーライドする関数 からデフォルトの引数を取得しません。 [例:

struct A { 
    virtual void f(int a = 7); 
}; 
struct B : public A { 
    void f(int a); 
}; 
void m() { 
    B* pb = new B; 
    A* pa = pb; 
    pa->f();   // OK, calls pa->B::f(7) 
    pb->f();   // error: wrong number of arguments for B::f() 
} 

- 終了例]

3

この呼び出しには2つの部分があります

  • xに渡すどのような値の決定 - これは、デフォルトのパラメータでありますA::foo、すなわち5であり、それはスタティックタイプのaです。コンパイル時。これについて考えるならば、これはコンパイラが持っている唯一の選択肢です。aに割り当てられた型について仮定してはならないからです。
  • aが指すオブジェクトの動的なタイプがstruct Bであるため、 - これはB::fooです。

したがって、出力として3 * 5が得られます。