1. 多重继承的问题三:多重继承可能产生多个虚函数表
编程说明:多重继承的问题三:多重继承可能产生多个虚函数表
#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* ppb = (BaseB*)pa;
cout << "sizeof(d) = " << sizeof(d) << endl;
cout << "Using pa to call funcA() ... " << endl;
pa->funcA();
cout << "Using pb to call funcB() ... " << endl;
pb->funcB();
cout << "Using pbb to call funcB() ... " << endl;
ppb->funcB(); // Expected to: BaseB::funcB(), but is: BaseA::funcA()
return 0;
}
输出结果:
sizeof(d) = 8
Using pa to call funcA() ...
BaseA::funcA()
Using pb to call funcB() ...
BaseB::funcB()
Using pbb to call funcB() ...
BaseA::funcA()
问题分析:强制类型转换有问题
解决办法:需要进行强制类型转换时,C++中推荐使用新式类型转换关键字—dynamic_cast
【与继承、虚函数有关时,使用dynamic_cast
关键字】
编程说明:使用dynamic_cast关键字
#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* ppb = dynamic_cast<BaseB*>(pa); // 使用dynamic_cast进行强制转换
cout << "sizeof(d) = " << sizeof(d) << endl;
cout << "Using pa to call funcA() ... " << endl;
pa->funcA();
cout << "Using pb to call funcB() ... " << endl;
pb->funcB();
cout << "Using pbb to call funcB() ... " << endl;
ppb->funcB();
return 0;
}
输出结果:
sizeof(d) = 8
Using pa to call funcA() ...
BaseA::funcA()
Using pb to call funcB() ...
BaseB::funcB()
Using pbb to call funcB() ...
BaseB::funcB()
2. 正确的使用多重继承
工程开发中的多重继承方式:
单继承某个类 + 实现(多个)接口
编程说明:正确的多重继承方式
#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);
Base* b = &d;
Interface1* pInt1 = &d;
Interface2* pInt2 = &d;
cout << "d.getI() = " << d.getI() << endl; // 100
// d.add(10);
pInt1->add(10);
cout << "d.getI() = " << d.getI() << endl; // 110
// d.divide(11);
pInt2->divide(11);
cout << "d.getI() = " << d.getI() << endl; //10
// d.minus(5);
pInt1->minus(5);
cout << "d.getI() = " << d.getI() << endl; // 5
// d.multiply(8);
pInt2->multiply(8);
cout << "d.getI() = " << d.getI() << endl; // 40
cout << endl;
cout << "pInt1 == b : " << b->equal(dynamic_cast<Base*>(pInt1)) << endl;
return 0;
}
输出结果
d.getI() = 100
d.getI() = 110
d.getI() = 10
d.getI() = 5
d.getI() = 40
pInt1 == b : 1
一些有用的工程建议:
(1) 先继承自一个父类,然后实现多个接口(单继承,多接口)
(2) 父类提供equal()
成员函数
(3)equal()
成员函数用于判断指针是否指向当前对象
(4) 与多重继承相关的强制类型转换用dynamic_cast
完成
3. 小结
- 多继承中可能出现多个虚函数表指针
- 与多重继承相关的强制类型转换用
dynamic_cast
完成 - 工程开发中采用单继承多借口的方式使用多继承
- 父类提供成员函数用于判断指针是否指向当前对象