2017-03-15 13 views
3

インタビューでこの質問がありました。私はそこでこれに答えることができませんでした。それが今のところどうして私はそれを得ることができないのですか?仮想関数のオーバーロード

#include <iostream> 
using namespace std; 

class Base 
{ 
public: 
    virtual void fun (int x = 0) 
    { 
     cout << "Base::fun(), x = " << x << endl; 
    } 
}; 

class Derived : public Base 
{ 
public: 
    virtual void fun (float x = 10.0) 
    { 
     cout << "Derived::fun(), x = " << x << endl; 
    } 
}; 


int main() 
{ 
    Derived d1; 
    Base *bp = &d1; 
    bp->fun(); 
    d1.fun(); 
    d1.fun(1.2); 
    return 0; 
} 

上記のコードの出力は次のとおりです:

Base::fun(), x = 0 
Derived::fun(), x = 10 
Derived::fun(), x = 1.2 

問題がある:私たちは楽しい()関数が過負荷を受けるの両方と言う(および最初のケースで ここ コードです(宣言にデフォルトの引数があるかどうかだけが異なるため)fun()の宣言がオーバーロードされることはできません。

void fun(int x = 0) 
void fun(float x = 10.0) 

これらの関数をオーバーロードすることはできません。

上記の両方のケースで矛盾があるようです。

状況を説明する関連記事/リンクが非常に役に立ちます。

+0

出力は何であり、その理由は? – NathanOliver

+0

最初のケースでは、実行時の多型性のため、出力はDerived :: fun()、x = 10.0になるはずです。 2番目と3番目のケースでは、どのように出力を決めるのですか? –

答えて

8

C++では、メンバー関数が基本クラス関数をオーバーライドするために、引数型は基本クラス関数の引数型と完全に一致しなければなりません。基本クラス関数はintで、派生クラスの関数はfloatであるため、オーバーライドとはみなされません。あなたはoverrideキーワードを使用してこれを見ることができます:

あなたのコード内で何が起こっている
class Base 
{ 
public: 
    virtual void fun (int x = 0) 
    { 
     cout << "Base::fun(), x = " << x << endl; 
    } 
}; 

class Derived : public Base 
{ 
public: 
    virtual void fun (float x = 10.0) override // Doesn't compile! 
    { 
     cout << "Derived::fun(), x = " << x << endl; 
    } 
}; 

は、C++は、あなたの関数ではなくオーバーライドより過負荷(同じ名前の別の関数)であると考えていることです。のは、このコードを見てみましょう:

ここ
Derived d1; 
Base *bp = &d1; 
bp->fun(); 

、ラインbp->fun()は、基本クラスのポインタを介してコールを使用しているため、C++は、呼び出すために機能するかを確認するためにBaseに見えます。それはBase::fun(int)を見つける。さて、その関数はvirtualとマークされているので、何かがオーバーラードしない限り、Base::fun(int)を呼び出します。しかし、オーバーライドされていないので、Base::fun(int)が呼び出されることになります。

この後の2行はどうですか?ここで

d1.fun(); 
d1.fun(1.2); 

あなたは静的な型Derivedのオブジェクトでこれらの関数を呼び出していることから、C++はDerivedクラスにfunという関数を見つけようとします。あなたの新しい関数Derived::fun(float)が見つかりました.C++がクラス内で名前の検索を行う方法のために、基底クラスではBase::fun(int)を検索しません。したがって、これらの呼び出しは両方ともDerived::fun(float)への呼び出しとして扱われるため、引数が指定されていないときに呼び出す関数についてのあいまいさはありません。コンパイラは、Baseタイプを見たこともありませんでした。だから、

は、要約する:あなたは 過負荷、ない オーバーライドを導入しました

  • の無効化キーワードを使用すると、今後このような問題を診断するのに役立ちます。ベースポインタのfun機能がintにかかるため、ベースポインタを通じてfunを呼び出す
  • は、intに取っfunという名前の関数を探します。オセイドがないので、バージョンはBaseになります。
  • 派生オブジェクトを通じてfunを呼び出すとfunというファンクションがDerivedで始まり、オーバーライドされます。
+0

最初のケースでは、実行時の多型はなぜ存在しないのですか? –

+1

@ YamanSinglaちょうど何が起こっているかを説明するために答えを更新しました。 – templatetypedef

+0

help @templatetypedefに感謝します。私は今実際に何が起こっているのか理解しています! –