如果我声明一个基类(或接口类)并为其一个或多个参数指定默认值,派生类是否必须指定相同的默认值,如果不是,哪些默认值将在派生类中体现?
附录:我也对如何在不同的编译器中处理这个问题以及在这种情况下对“推荐”实践的任何输入感兴趣。
虚拟可能有默认值。基类中的默认值不会被派生类继承。
使用哪个默认值——即,基类’或派生类’——由用于调用函数的静态类型决定。如果通过基类对象、指针或引用调用,则使用基类中表示的默认值。相反,如果您通过派生类对象、指针或引用调用,则使用派生类中表示的默认值。标准报价下面有一个例子可以证明这一点。
一些编译器可能会做一些不同的事情,但这就是 C03 和 C11 标准所说的:
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() }
虚函数调用 (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这里使用 s 而不是classes 只是为了简洁——除了默认可见性之外,几乎在所有class方面struct都完全相同。
struct
class
#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 和 GCC 4.4 上)是:
Base 42 Der 42 Der 84