54-多重继承(下)单继承多接口
来源:互联网 发布:java 方法名 编辑:程序博客网 时间:2024/06/14 00:14
1、多重继承问题三
Derived继承BaseA和BaseB,如果AB中都含有1个虚函数,那么Derived就会叠加产生2个虚函数表指针指向这两个虚函数表
#include <iostream>#include <string>using namespace std;class BaseA{public: virtual void funcA() { cout << "BaseA::funcA()" << endl; }};class BaseB{public: virtual void funcB() { cout << "BaseB::funcB()" << endl; }};class Derived : public BaseA, public BaseB{};int main(){ Derived d; BaseA* pa = &d; BaseB* pb = &d; BaseB* pbe = (BaseB*)pa; // oops!! 这种强制类型转化有问题 BaseB* pbc = dynamic_cast<BaseB*>(pa); //在与继承,与虚函数相关的强制类型转换时,使用dynamic_cast关键字 //dynamic_cast对指针进行了修正,使pbc指向pb的位置 //Derived没有任何成员变量,验证虚函数表指针存在, cout << "sizeof(d) = " << sizeof(d) << endl; //8字节 cout << "Using pa to call funcA()..." << endl; pa->funcA();//符合预期,父类指针指向子类,调用子类的成员函数 cout << "Using pb to call funcB()..." << endl; pb->funcB(); cout << "Using pbc to call funcB()..." << endl; pbc->funcB(); //将pa指针指向的d对象,通过BaseB*转换为指向pb, //然后调用pbe->funcB()函数,想要输出"BaseB::funcB()" //其实BaseB* pbe = (BaseB*)pa;后,pbe指向的还是pa!!! //所以调用的是"BaseA::funcA()",这种强制转换造成了内存未按预期对齐 cout << endl; cout << "pa = " << pa << endl; cout << "pb = " << pb << endl; cout << "pbe = " << pbe << endl; cout << "pbc = " << pbc << endl; return 0;}sizeof(d) = 8Using pa to call funcA()...BaseA::funcA()Using pb to call funcB()...BaseB::funcB()Using pbc to call funcB()...BaseB::funcB()pa = 0x7ffed5f93090pb = 0x7ffed5f93098pbe = 0x7ffed5f93090pbc = 0x7ffed5f93098
2、解决方案
在d对象里面存在两个指向虚函数表的指针,这是由于继承而来的。
先用pa指向d对象,再用pb指向d对象,pa和pb指向的位置不一样
接下来通过pa进行强制类型转换,将转换的结果给pbb指针,此时pbb所指向的位置为pa的位置,不是pb的位置。
虚函数调用的过程:
首先先获取pa的地址通过地址找到虚函数表指针vptr1,进而通过
虚函数表指针去找虚函数表中的函数地址,找到funcA的函数地址
同理pb一样;
pbb也是找到vptr1的虚函数表,但是里面不存在funcB的函数,只有函数funcA的函数,最终调用funcA函数,
所以BaseB* pbb = (BaseB*)pa; 这个强制类型转换有问题
所以要使用BaseB* pbb =dynamic_cast
3、正确的使用多重继承
#include <iostream>#include <string>using namespace std;class Base{protected: int mi;public: Base(int i) { mi = i; } int getI() { return mi; } bool equal(Base* obj)//判断参数的指针指向的是否为当前对象 { return (this == obj); }};class Interface1{public: virtual void add(int i) = 0; //纯虚函数为抽象类,该类只能继承不能实例化 virtual void minus(int i) = 0;};class Interface2{public: virtual void multiply(int i) = 0; virtual void divide(int i) = 0;};class Derived : public Base, public Interface1, public Interface2{public: Derived(int i) : Base(i) { } void add(int i) { mi += i; } void minus(int i) { mi -= i; } void multiply(int i) { mi *= i; } void divide(int i) { if( i != 0 ) { mi /= i; } }};int main(){ Derived d(100); Derived* p = &d; Interface1* pInt1 = &d; Interface2* pInt2 = &d; cout << "p->getI() = " << p->getI() << endl; // 100 pInt1->add(10); pInt2->divide(11); pInt1->minus(5); pInt2->multiply(8); cout << "p->getI() = " << p->getI() << endl; // 40 cout << endl; cout << "pInt1 == p : " << p->equal(dynamic_cast<Base*>(pInt1)) << endl; cout << "pInt2 == p : " << p->equal(dynamic_cast<Base*>(pInt2)) << endl; //p->equal(pInt1)这样的话会造成类型不匹配,必须使用dynamic_cast进行强制类型转化 //hellp.cpp:84:48: error: no matching function for call to ‘Derived::equal(Interface1*&)’ // cout << "pInt1 == p : " << p->equal((pInt1)) << endl; return 0;}p->getI() = 100p->getI() = 40pInt1 == p : 1pInt2 == p : 1
4、
5、小结
阅读全文
0 0
- 54-多重继承(下)单继承多接口
- JAVA 单继承 与 接口 多重继承
- JAVA 单继承 与 接口 多重继承
- JAVA 单继承 与 接口 多重继承
- 接口与多重继承
- 接口与多重继承
- 接口多重继承
- 多重继承(接口技术)
- 接口与多重继承
- 多重继承和接口
- java类单继承 接口多继承
- 继承(单继承、多继承、菱形继承、虚继承)
- 多重继承和单重继承
- 多继承与多重继承
- 多继承和多重继承
- 多重继承(菱形继承)
- 接口与多重继承<转>
- vb6不支持多重接口继承
- Java 接口类型的创建及使用
- Imagej分析所有气泡的粒径
- 正则表达式的一些案例
- 常考的地址协议
- struts2 从入门到总结
- 54-多重继承(下)单继承多接口
- 将数字字符串转化成整数值
- 实力亲测 | 如何用云盾WAF做漏洞急救
- 使用快照来迁移实例
- 微信TOKEN总是验证失败的解决方案。
- sqlserver text类型判断是否为空
- 安装BBR无法正常冲浪
- docker+selenium web自动化测试环境的部署
- Android SharePreferences 进行数据进行加密