C++ 虚函数的默认参数问题
C++缺省参数问题
一般函数
-
有函数声明时,默认参数可以放在函数声明或者定义中,但只能放在二者之一,建议放在声明中
-
没有函数(原型)时,默认参数在函数定义时指定
static void Test0(int a = 0); ... void Test0(int a) { cout << a << endl; } ... void Test1(int a, int b = 2, char c = '3', string d = "4") { cout << a << endl << b << endl << c << endl << d << endl; }
-
一旦某个参数开始指定默认值,它右边的所有参数都必须指定默认值:函数声明时,必须按照从右向左的顺序,依次给与默认值
-
在调用具有默认参数的函数时,若某个有默认参数的参数使用了默认参数, 它右边的所有参数都使用默认参数:函数调用时,必须按照从左向右的顺序,依次赋值
#include<bits/stdc++.h> using namespace std; static void Test0(int a = 0); static void Test1(int a, int b = 2, char c = '3', string d = "4"); int main() { Test0(); Test1(1); //'2'会转换成int,执行Test1 Test1(1, '2'); return 0; } void Test0(int a) { cout << a << endl; } void Test1(int a, int b, char c, string d) { cout << a << endl << b << endl << c << endl << d << endl; }
类的一般成员函数
- 同上
类的虚函数
结论:决不要重新定义继承而来的缺省参数值
#include<bits/stdc++.h>
using namespace std;
class A {
public:
virtual void Test0(int a = 5) = 0;
};
class B : public A {
public:
virtual void Test0(int a = 6) override {
cout << a << endl;
}
};
int main() {
A* a = new B();
a->Test0();
return 0;
}
原因:
-
虚函数是动态绑定的,即具体被调用的虚函数由那个对象的动态类型决定
-
缺省参数是静态绑定的,即编译阶段就确定了虚函数的默认参数一定来自Base类;
这样做的原因是:运行效率。如果缺省参数被动态绑定,需要类似查虚表的机制,这将比现在采用的在编译阶段确定缺省值的机制更慢更复杂
比如:上方代码如果调用Test0()
-
参数压栈
-
返回地址压栈
-
调用函数:因为虚函数,需要虚表找到函数指针,跳到函数实际地址执行函数
注意到此时参数已经压栈,虽然可以用类似的机制实现动态绑定,但没必要
-