面试题答案
一键面试1. 继承方式对多态性相关概念的影响
虚函数
- public继承:在public继承下,基类的虚函数在派生类中仍然保持虚函数的性质。这意味着派生类可以重写(override)这些虚函数,以实现多态行为。
- private继承:基类的虚函数在private继承的派生类中变为private成员函数。虽然派生类内部可以重写这些函数,但对于外部代码,无法通过基类指针或引用调用派生类重写的虚函数,多态性无法在类外部体现。
- protected继承:基类的虚函数在protected继承的派生类中变为protected成员函数。与private继承类似,外部代码无法通过基类指针或引用调用派生类重写的虚函数,多态性在类外部受限。
函数重写
- public继承:派生类通过重写基类的虚函数来实现多态。重写的函数需要满足函数签名(参数列表和返回类型)与基类虚函数一致(协变返回类型除外)。通过基类指针或引用调用虚函数时,会根据对象的实际类型调用相应派生类的重写函数。
- private继承:尽管派生类可以重写基类虚函数,但由于访问权限问题,外部代码无法通过基类指针或引用访问到派生类重写的函数,不能实现多态调用。
- protected继承:同样,派生类可重写基类虚函数,但外部代码不能通过基类指针或引用调用派生类重写的函数,多态性受限。
对象切片
- public继承:对象切片发生在将派生类对象赋值给基类对象时,会丢失派生类特有的部分数据。在多态调用中,如果通过值传递(而非指针或引用),对象切片会导致调用的是基类版本的虚函数,破坏多态性。
- private和protected继承:由于外部代码无法直接访问派生类对象(通过基类接口),对象切片的场景在这些继承方式下对于外部代码来说不太容易出现,但在类内部或友元函数中仍可能发生类似行为,同样可能影响多态性。
2. 代码示例
#include <iostream>
class Base {
public:
virtual void print() {
std::cout << "Base::print()" << std::endl;
}
};
// public继承
class PublicDerived : public Base {
public:
void print() override {
std::cout << "PublicDerived::print()" << std::endl;
}
};
// private继承
class PrivateDerived : private Base {
public:
void print() {
std::cout << "PrivateDerived::print()" << std::endl;
}
};
// protected继承
class ProtectedDerived : protected Base {
public:
void print() {
std::cout << "ProtectedDerived::print()" << std::endl;
}
};
int main() {
// public继承多态测试
Base* publicPtr = new PublicDerived();
publicPtr->print(); // 输出 PublicDerived::print()
delete publicPtr;
// private继承测试
PrivateDerived privateObj;
// Base* privatePtr = &privateObj; // 错误,无法从PrivateDerived* 转换为 Base*
// privatePtr->print(); // 无法通过此方式调用
// protected继承测试
ProtectedDerived protectedObj;
// Base* protectedPtr = &protectedObj; // 错误,无法从ProtectedDerived* 转换为 Base*
// protectedPtr->print(); // 无法通过此方式调用
return 0;
}
在上述代码中,PublicDerived
通过 public
继承 Base
,可以实现多态调用 print
函数。而 PrivateDerived
和 ProtectedDerived
分别通过 private
和 protected
继承 Base
,外部代码无法通过 Base
指针或引用调用它们重写的 print
函数,多态性受到限制。