多态的核心--虚函数--静态类型和动态类型

静态类型(在编译时可知的引用类型或指针类型)

动态类型(指针或引用所绑定的对象的类型这是仅在运行时可知的)

#include <iostream>
using namespace std;
class A
{
public:
	A()
	{
		fun();
	};

//private: //如果这里设置为private则编译不通过
	virtual void fun(int i=10) 
	{
		cout<<"A init; "<<i<<endl;;
	}
};
class B:public A
{
public:
	B(){
		cout<<"B init2"<<endl;
	};
	
	virtual void fun2()
	{
		cout<<"B fun2 "<<endl;
	}
	virtual  void fun(int i=88)
	{
		cout<<"B init "<<i<<endl;
	}
};
int main()
{
	B b;
	A* p=&b;
	p->fun();
	system("pause");
	return 0;
}


 


为什么编译不通过?

(当设置为public 时,输出: B init 10 )

过程:

1,在编译阶段,p->fun(); 只是按其静态类型来处理的, 在这里为类型A。

也就是说,碰到p->fun(); 编译器就当作调用A的fun来进行相应的检查和处理。

例如 A类中 fun()设为private的时,类用户是不能访问的,所以编译出错。

2,运行时,

B b; 这条语句执行了以下操作:(PS:类的非静态成员函数都会编译加一个指针参数,指向调用该函数的对象,我们平常用的this就是该指针的值)

(1)调用基类的构造函数,通过附加的this指针(指向的是b),把b对应的虚函数表中的第一项改为:A::fun(int)

(2)调用派生类的构造函数,能过附加的this指针(指向b),把b对应的函数表中的第一项改为:B:fun(int),把刚才的覆盖了。

PS:虚函数表里的每一项 都保存 着函数指针 ,最后是一项是一个结束标记。

所以执行p->fun();的时候,实际上执行的B::fun()。

 

 为什么输出 10

C++的注意条款中有一条" 绝不重新定义继承而来的缺省参数值" (Effective C++ Item37, never redefine a function's inherited default parameter value) 也是同样的道理。

如果通过基类的引用或指针调用虚函数,但实际执行的是派生类中定义的版本,这时就可能会出现问题。

在这种情况下,为虚函数的基类版本定义的默认实参将传给派生类定义的版本,而派生类版本是用不同的默认实参定义的。

 

更多解析请看http://www.cppblog.com/xczhang/archive/2008/01/20/41508.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值