面试题答案
一键面试多重继承带来的与代码复用相关的复杂性
- 命名冲突:多个基类可能包含同名的成员(函数或变量),这会导致在派生类中使用这些成员时产生歧义。例如,两个基类
Base1
和Base2
都有一个名为func
的函数,当派生类Derived
从这两个基类继承时,调用Derived::func
就不知道该调用哪个基类的func
。 - 菱形继承问题:当一个派生类从多个基类继承,而这些基类又继承自同一个基类时,会形成菱形结构。这会导致在派生类中,同一个基类的成员被多次继承,造成数据冗余和访问混乱。例如,
Base
类被Derived1
和Derived2
继承,然后FinalDerived
从Derived1
和Derived2
继承,FinalDerived
中就会有两份Base
类的成员。
解决命名冲突
通过指定作用域来明确调用哪个基类的成员。
#include <iostream>
class Base1 {
public:
void func() {
std::cout << "Base1::func" << std::endl;
}
};
class Base2 {
public:
void func() {
std::cout << "Base2::func" << std::endl;
}
};
class Derived : public Base1, public Base2 {
public:
void callBase1Func() {
Base1::func();
}
void callBase2Func() {
Base2::func();
}
};
int main() {
Derived d;
d.callBase1Func();
d.callBase2Func();
return 0;
}
解决菱形继承问题
使用虚继承。虚继承使得从不同路径继承过来的同名基类成员在派生类中只有一份拷贝。
#include <iostream>
class Base {
public:
int data;
};
class Derived1 : virtual public Base {
};
class Derived2 : virtual public Base {
};
class FinalDerived : public Derived1, public Derived2 {
public:
void setData(int value) {
data = value;
}
void printData() {
std::cout << "Data: " << data << std::endl;
}
};
int main() {
FinalDerived fd;
fd.setData(10);
fd.printData();
return 0;
}
在上述代码中,Derived1
和 Derived2
对 Base
类采用虚继承,这样 FinalDerived
中 Base
类的成员 data
只有一份拷贝,避免了数据冗余和访问混乱。