看下列代码执行结果,你猜一猜会输出什么?
#include<iostream>
using namespace std;
struct A {virtual void fun(int a = 10) {cout << "A,a="<<a;}
};
struct B :public A {void fun(int a = 5) {cout <<"B,a="<<a;}
};
int main() {A* a = new B;a->fun();
}
我们看运行结果:
通过运行结果可以得知发生了多态但是默认参数的值是父类中的。
汇编中默认参数只会在传参中体现为一个字面量所以看编译的中间代码
int main ()
{void * D.53827;struct A * a;int D.53825;bool D.49666;void * D.49598;int (*) () * _1;int (*) () _2;void * _5;void * _6;bool _7;bool _9;int _12;<bb 2> :_5 = operator new (8);_6 = _5;_7 = 1;B::B (_6);_9 = 0;a_10 = _6;_1 = a_10->_vptr.A;_2 = *_1;OBJ_TYPE_REF(_2;(struct A)a_10->0B) (a_10, 10);_12 = 0;<bb 3> :
<L0>:return _12;}void B::B (struct B * const this)
{struct A * _1;int (*) () * _2;<bb 2> :_1 = &this_3(D)->D.49586;A::A (_1);_2 = &_ZTV1B + 16;this_3(D)->D.49586._vptr.A = _2;return;}void A::A (struct A * const this)
{int (*) () * _1;<bb 2> :_1 = &_ZTV1A + 16;this_3(D)->_vptr.A = _1;return;}void B::fun (struct B * const this, int a)
{struct basic_ostream & D.53828;struct basic_ostream & _1;struct basic_ostream & _4;<bb 2> :_4 = std::operator<< <std::char_traits<char> > (&cout, "B,a=");_1 = _4;std::basic_ostream<char>::operator<< (_1, a_5(D));return;}void A::fun (struct A * const this, int a)
{struct basic_ostream & D.53829;struct basic_ostream & _1;struct basic_ostream & _4;<bb 2> :_4 = std::operator<< <std::char_traits<char> > (&cout, "A,a=");_1 = _4;std::basic_ostream<char>::operator<< (_1, a_5(D));return;}
可以看出默认参数在编译时遇到函数调用直接获取了字面量,那么它的生效时间是先于动态多态的,这个时期无论默认参数的字面量存储在代码区还是静态区都不会影响选择,因为这个阶段并没有发生多态也就无从改变默认参数的使用,可以说默认参数就是在编译时期确认函数参数的一种静态行为。
同时这并不是说函数参数是静态的,至少C/C++中函数参数只能是局部的栈区变量(用static声明也会失效),或者可以简单的理解为一种标识符,标识函数调用时传参的要求或者说唯一标识一个函数。
下面一个例子可以证明函数参数不存在static的说法。
#include<iostream>
using namespace std;
struct Test
{int a;
};
struct A {Test& fun1(Test ptr = { 6 }) {return ptr;}Test& fun2(Test ptr) {return ptr;}Test& fun3(static Test ptr) {return ptr;}Test& fun4(static Test ptr = {6}) {return ptr;}Test& fun5() {static Test ptr{ 6 };return ptr;}
};int main() {A a;Test t{ 6 };Test*cur1=&a.fun1();Test*cur2= &a.fun2(t);Test*cur3 = &a.fun3(t);Test*cur4 = &a.fun4();Test*cur5 = &a.fun5();cout << cur1->a << " " << cur2->a << " " << cur3->a << " " << cur4->a<<" "<<cur5->a<<endl;
}
根据返回值可以得出结论static并没有成功修饰到形参,这个其实可以从两方面理解。
- 函数形参并没有静态类型的需求。
- static修饰词就是那样定义的,详情看这篇