7

私はC++に取り組んでいます。以下は私のコードです:

#include <iostream>
using namespace std;
class base
{
        public:
        virtual void display(int a = 4)
        {
                cout << "base ::  "<<  a*a << endl;
        }
};

class derived : public base
{
        public:
        void display(int b = 5)
        {
                cout << " Derived :: " << b*b*b <<  endl;
        }
};

int main()
{
        base *bobj;
        derived dobj;
        bobj = &dobj;
        bobj->display();
        return 0;
}

出力は次のとおりです。

Derived :: 64

Baseクラスの関数が呼び出されますが、派生関数のパラメーターのデフォルト値が使用されます。派生クラスメソッドdisplay()が基本クラスメソッドの引数値をとるのはなぜですか?

4

5 に答える 5

7

へのポインタを介して呼び出しているためですbase。それがどのように機能するかです。

引数は、実際の呼び出しの前に引数スタック(またはレジスタ内)にプッシュされます。パラメータへのポインタがbaseあり、パラメータがないため、デフォルト4が関数に渡されます。次に、正しい関数が呼び出されます(derived::display)が、baseのデフォルトパラメータを使用します。もちろん、これは実装の詳細ですが、動作は標準です。

C ++ 03 8.4 / 10

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

私は引用に重点を置きますが、全体はかなり自明です。

dobj.display();

125(5 ^ 3)を出力します。

于 2012-09-03T09:16:24.373 に答える
2

デフォルトの引数は、呼び出し元によって挿入されます。あなたのコードはと同等です

class base {
public:
    virtual void display(int a) { cout << "base ::  "<<  a*a << endl; }
    inline void display(void) { display(4); }
};

ポインタを介して呼び出す場合base、基本クラスのデフォルト値が挿入されます。

于 2012-09-03T09:19:30.870 に答える
2

規格はそれをすべて述べています:

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

    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()
    }
    — end example ]
于 2012-09-03T09:22:09.663 に答える
0

つまり、ポインタを使用->して関数を呼び出す場合、この場合はDerivedクラスのオブジェクトである決定を行うためにポイントされているオブジェクトを使用します。

仕様が言うように...

仮想関数呼び出しは、オブジェクトを示すポインターまたは参照の静的型によって決定される仮想関数の宣言でデフォルトの引数を使用します。派生クラスのオーバーライド関数は、オーバーライドする関数からデフォルトの引数を取得しません。

于 2012-09-03T09:20:55.420 に答える
0

あまり工夫されていないテスト設定を作成すると、次のことが明らかになります。

#include "base.hpp"

int compute(base * p)
{
    return p->display();
}

現在、2つのことが明らかです。

  1. デフォルトの引数は、で指定されたデフォルトの引数からのみ取得できる可能性がありますbase

  2. displayは仮想メンバー関数であるため、実際のディスパッチは動的です。

于 2012-09-03T09:29:58.543 に答える