double-patching 通过两次虚函数实现在VS上测试(More effective C++233)
来源:互联网 发布:剑网3霸刀捏脸数据 编辑:程序博客网 时间:2024/06/07 03:28
class A;class B;class Vbase{public:virtual void Test(Vbase & obj)=0;virtual void Test(A &obj)=0;virtual void Test(B &obj)=0;};class A:public Vbase{public:virtual void Test(Vbase & aVbase){aVbase.Test(*this);cout<<"second dispatch"<<endl;}virtual void Test(A &aA){cout<<"A + A called"<<endl;}virtual void Test(B &aB){cout<<"B + A called"<<endl;}};class B:public Vbase{public:virtual void Test(Vbase & aVbase){aVbase.Test(*this);cout<<"second dispatch"<<endl;}virtual void Test(A &aA){cout<<"A + B called"<<endl;}virtual void Test(B &aB){cout<<"B + B called"<<endl;}};
class Vbase{public:virtual void Test(Vbase &){cout<<"base\n";}};class B;class A:public Vbase{public:virtual void Test(Vbase & aVbase){aVbase.Test(*this);cout<<"second dipatch"<<endl;}virtual void Test(A &aA){cout<<"A + A called"<<endl;}virtual void Test(B &aB){cout<<"A + B called"<<endl;}};class B:public Vbase{public:virtual void Test(Vbase & aVbase){aVbase.Test(*this);cout<<"second dipatch"<<endl;}virtual void Test(A &aA){cout<<"B + A called"<<endl;}virtual void Test(B &aB){cout<<"B + B called"<<endl;}};int _tmain(int argc, _TCHAR* argv[]){Vbase *p1 = new A();Vbase *p2 = new B();p1->Test(*p2);cout<<"second phase"<<endl;p2->Test(*p1);return 0;}一直不是按照静态类型选择重载版本,调用陷入死递归直到栈耗尽
完全按照书本信息,在基类里将每一个声明为纯虚函数,果然就OK了,看来声明一个函数是虚函数必须要从基类开始(这个基类通常是静态类型的入口),并不是在所有派生类中将函数声明为虚函数就OK的,因为此时基类函数没有相应的虚表项,此时它将直接进行静态的链接?
后来关闭基类虚接口定义中的最后一个,果然在第二个测试结果执行异常,因为执行的是静态绑定,多分发一次得到错误的调用结果,而第一个测试用例正确,看来还是没有从整个流程层面清晰地认识虚函数调用机制,并不掌握执行动态绑定的时机,并不是相应子类的函数都声明为虚函数的时候编译器就会执行动态绑定,编译器是通过静态类型是基类的入口进入的,当检查基类没有相应的虚表项就执行了静态绑定;
后续:来个最简单的测试结束(纠正平时很容易犯的一个严重问题,动态要从也只需从基类声明virtual,如果基类没有声明相应借口,绑定时的入口信息编译器会报错,没有定义基类的相应符号,如果声明了接口而没有加virtual关键字,一个严重的隐患就此种下了,编译器会发现其没有虚表项直接进行了静态绑定)
class A;class B;class Vbase{public:void Test(){cout<<"Based called"<<endl;}};class A:public Vbase{public:virtual void Test(){cout<<"A called"<<endl;}};class B:public Vbase{public:virtual void Test() //每个分支都有但入口没有 没用{cout<<"B called"<<endl;}};int _tmain(int argc, _TCHAR* argv[]){Vbase *p1 = new A();p1->Test();}输出是
Based called 不是我们想要的吧,以后要小心了
- double-patching 通过两次虚函数实现在VS上测试(More effective C++233)
- C++在构造函数中防止资源泄露(9)---《More Effective C++》
- More Effective C++:通过引用捕获异常
- More Effective C++:通过引用捕获异常
- 《More Effective C++》学习心得(七) 构造函数私有化
- 《More Effective C++》条款27:如何让类对象只在栈(堆)上分配空间?
- 《More Effective C++》条款27:如何让类对象只在栈(堆)上分配空间?
- 《More Effective C++》条款27:如何让类对象只在栈(堆)上分配空间?
- 《More Effective C++》条款27:如何让类对象只在栈(堆)上分配空间?
- 《More Effective C++》条款27:如何让类对象只在栈(堆)上分配空间?
- 《More Effective C++》条款27:如何让类对象只在栈(堆)上分配空间?
- More Effective C++:避免缺省构造函数
- More Effective C++----(10)在构造函数中防止资源泄漏
- C++之通过引用(reference)捕获异常(12)---《More Effective C++》
- More Effective C++:通过引用捕获异常(转)
- More Effective C++----(13)通过引用捕获异常
- 《More Effective C++》学习心得(一)
- 《More Effective C++》学习心得(二)
- 【搬家】生活小记 2011-08-05 再谈理想
- java socket参数详解:OOBInline和UrgentData
- java远程通讯技术及简单实现
- BusyBox 简化嵌入式 Linux 系统
- 初试paoding-rose
- double-patching 通过两次虚函数实现在VS上测试(More effective C++233)
- python模块之email: 电子邮件编码解码 (一、解码邮件)
- Objective-c 第12-13-14-15章
- bat 将当前目录的文件复制到指定目录
- 内存不足 java.lang.OutOfMemoryError: Java heap space
- java中的String类常量池详解
- VK Cup 2012 Qualification Round 2 E 无语凝噎
- Compiling Meshlab
- 推送通知