1. ホーム
  2. c++

[解決済み] 仮想関数にデフォルトのパラメータを持たせることはできますか?

2022-04-14 03:59:38

質問

ベースクラス(またはインターフェースクラス)を宣言し、そのパラメータの1つ以上にデフォルト値を指定した場合、派生クラスも同じデフォルト値を指定しなければならないのでしょうか、そうでなければ、どのデフォルト値が派生クラスで明示されるのでしょうか。

追記:異なるコンパイラ間でどのように扱われるのか、またこのシナリオにおける「推奨される」実践方法についての意見にも興味があります。

解決方法は?

仮想通貨はデフォルトを持つことができます。 ベースクラスのデフォルトは、派生クラスには継承されません。

どちらのデフォルトを使うか、つまりベースクラスか派生クラスかは、 関数を呼び出す際に使用する静的型によって決まります。 ベースクラスのオブジェクトやポインタ、参照を通じて呼び出した場合は、 ベースクラスで指定されたデフォルトが使用されます。 逆に、派生クラスのオブジェクトやポインタ、参照を通じて呼び出した場合は、派生クラスで示されるデフォルトが使用されます。 標準引用文の下に、このことを示す例があります。

コンパイラによっては異なる動作をする場合もありますが、C++03およびC++11標準ではこのように規定されています。

<ブロッククオート

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()
}


どのようなデフォルトが拾われるのか、サンプルプログラムを紹介します。 ここでは struct ではなく、ここでは class は、単に簡略化のために --。 classstruct は、デフォルトの可視性を除いて、ほとんどすべての面でまったく同じです。

#include <string>
#include <sstream>
#include <iostream>
#include <iomanip>

using std::stringstream;
using std::string;
using std::cout;
using std::endl;

struct Base { virtual string Speak(int n = 42); };
struct Der : public Base { string Speak(int n = 84); };

string Base::Speak(int n) 
{ 
    stringstream ss;
    ss << "Base " << n;
    return ss.str();
}

string Der::Speak(int n)
{
    stringstream ss;
    ss << "Der " << n;
    return ss.str();
}

int main()
{
    Base b1;
    Der d1;

    Base *pb1 = &b1, *pb2 = &d1;
    Der *pd1 = &d1;
    cout << pb1->Speak() << "\n"    // Base 42
        << pb2->Speak() << "\n"     // Der 42
        << pd1->Speak() << "\n"     // Der 84
        << endl;
}

このプログラムの出力は(MSVC10とGCC4.4の場合)です。

Base 42
Der 42
Der 84