直接看这段代码
- class CBase
- {
- public:
- virtual int func(int num=1) const //虚函数
- {
- cout<<"CBase function! "<<num<<endl;
- return 0;
- }
- int fun2()
- {
- cout<<"CBase function2! "<<endl;
- return 0;
- }
- };
- class CDerive : public CBase
- {
- public:
- int func(int num=2) const //在派生类中重新定义虚函数
- {
- cout<<"CDerive function! "<<num<<endl;
- return 0;
- }
- int fun2()
- {
- cout<<"CDerive function2! "<<endl;
- return 0;
- }
- };
- int main()
- {
- CDerive* obj1=new CDerive;
- CBase* p1=obj1;
- p1->func();
- obj1->func();
- p1->fun2();
- obj1->fun2();
- delete obj1;
- return 0;
- }
代码执行的结果为:
CDerive function! 1
CDerive function! 2
CBase function2!
CDerive function2!
Press any key to continue
都明白了不?
不明白先看点背景知识。
静态多态性:函数多态性——函数重载
模板多态性——C++模板(类模板、函数模板)
动态多态性:虚函数(只有用地址才能实现动态多态性)
只有采用“指针->函数()”或“引用变量.函数()”的方式调用C++类中的虚函数才会执行动态绑定。对于C++中的非虚函数,因为其不具备动态绑定的特征,所以不管采用什么样的方式调用,都不会执行动态绑定。
C++语言成员函数的调用和绑定方式总结
代码形式 对于虚函数 对于非虚函数
作用 绑定方式 作用 绑定方式
类名::函数() 调用指定类的指定函数 静态绑定 调用指定类的指定函数 静态绑定
对象名.函数() 调用指定对象的指定函数 静态绑定 调用指定对象的指定函数 静态绑定
引用变量.函数() 调用被引用对象所属类的指定函数 动态绑定 调用引用变量所属类的指定函数 静态绑定
指针->函数() 调用被引用对象所属类的指定函数 动态绑定 调用指针变量所属类的指定函数 静态绑定
注:被引用对象所属类 是 指针 或 引用 指向的对象的实际类型;
引用变量所属类、指针变量所属类 是 定义 引用变量、指针变量的类型;
以上两种类型可能相同,也可能不同。
从上表可以看出,执行动态绑定的只有通过地址,即只有通过指针或引用变量才能实现,而且还必须是虚函数。从概念上来说,虚函数机制只有在应用于地址时才有效,因为地址在编译阶段提供的类型信息不完全。
先看第一条:
CDerive function! 1
由p1->func();调用的虚函数,虽然p1为基类指针,但是调用到的函数却应该是被引用对象所属类的指定函数,也就是子类的虚函数。
CDerive* obj1=new CDerive;已经决定了p1能调用到的是子类虚函数,这就是动态绑定。
但是再看看后面的参数1,子类虚函数int func(int num=2) const 参数应该是2,这个我还不能很好的解释。(*-*,跟飞雪沟通沟通再补充。。)
因为,参数是在编译时绑定,所以p1->func();的缺省参数还是基类函数的参数,没有跟上动态绑定。只能这样说了,反正飞雪说多了,我也搞不清。
第2条:
CDerive function! 2
这是我们需要的结果,不用解释了吧
第3条:
CBase function2!
静态绑定,根据指针类型调用。
第4条同3