#include <iostream>
using namespace std;
class Base {
public:
virtual void fun(int x = 111) {
cout << "Base::fun(), x = " << x << endl;
}
};
class Derived : public Base {
public:
virtual void fun(int x) {
cout << "Derived::fun(), x = " << x << endl;
}
};
int main() {
Derived d1;
Base* bp = &d1;
bp->fun();
return 0;
}
运行结果:
Derived::fun(), x = 111
根据输出结果,可以看到最终调用的是子类的fun()函数,并且使用了基类函数fun()中的默认值。
默认参数是不会做为判断函数是否相同的因素的。所以子类与基类中的fun()函数被认为是相同的,这样基类的fun()函数被隐藏了。
另外,默认值是在编译期间使用的。当编译器看到一个函数调用中的某个参数缺失了,它就会用默认提供的值来替换。
因此,上面程序中,x的值在编译期间被替换了,在运行时期间调用的是子类的fun()函数。
2.基类默认值覆盖子类默认值
参考下面程序的结果
#include <iostream>
using namespace std;
class Base {
public:
virtual void fun(int x = 111) {
cout << "Base::fun(), x = " << x << endl;
}
};
class Derived : public Base {
public:
virtual void fun(int x = 222) { // 注意这里的变化
cout << "Derived::fun(), x = " << x << endl;
}
};
int main() {
Derived d1;
Base* bp = &d1;
bp->fun();
return 0;
}
运行结果:
Derived::fun(), x = 111
这个程序的结果与第1节中程序是一样的。原因也是一样的,默认值在编译期间被替换了。
bp是基类类型的指针,调用fun函数时,编译器用111替换掉了222。
3.基类指定值覆盖子类默认值
参考下面程序的结果
#include <iostream>
using namespace std;
class Base {
public:
virtual void fun(int x) {
cout << "Base::fun(), x = " << x << endl;
}
};
class Derived : public Base {
public:
virtual void fun(int x = 222) { // 注意这里的变化
cout << "Derived::fun(), x = " << x << endl;
}
};
int main() {
Derived d1;
Base* bp = &d1;
bp->fun(333);
return 0;
}
运行结果:
Derived::fun(), x = 333
这个更容易理解。调用函数时,如果有指定形参值,则优先用指定值。只有没有指定时,才会用默认值。
总的来说,应该尽量避免在虚函数中使用默认值,这样可以避免遇到一些意想不到的结果。