面试题答案
一键面试- 关键要素
- 虚函数:
- 虚函数是C++实现运行时多态的基础。在基类中使用
virtual
关键字声明的成员函数称为虚函数。它为派生类提供了一个可覆盖(override)的接口。通过将函数声明为虚函数,编译器会在编译时为该函数的调用生成特殊的代码,使得在运行时能够根据对象的实际类型来决定调用哪个版本的函数。
- 虚函数是C++实现运行时多态的基础。在基类中使用
- 虚函数表(vtable):
- 每个包含虚函数的类都有一个虚函数表。虚函数表是一个数组,其中存储了类中所有虚函数的地址。当类对象被创建时,会隐含地包含一个指向该虚函数表的指针(vptr)。对于派生类,如果它覆盖了基类的虚函数,那么虚函数表中对应虚函数的地址会被替换为派生类中该虚函数的地址。这样,在运行时通过对象的虚函数表指针(vptr)就可以找到实际要调用的虚函数地址。
- 指针或引用:
- 运行时多态必须通过指针或引用进行函数调用。当使用对象的指针或引用调用虚函数时,编译器会根据指针或引用所指向对象的实际类型(而不是指针或引用本身的类型)来查找虚函数表,并调用相应的虚函数。这是因为指针或引用在运行时可以指向不同类型的对象(基类指针或引用可以指向派生类对象),从而实现运行时根据对象实际类型来决定调用哪个虚函数版本。
- 虚函数:
例如:
class Base {
public:
virtual void print() {
std::cout << "Base::print()" << std::endl;
}
};
class Derived : public Base {
public:
void print() override {
std::cout << "Derived::print()" << std::endl;
}
};
int main() {
Base* basePtr = new Derived();
basePtr->print();// 通过基类指针调用虚函数,实际调用的是Derived::print()
delete basePtr;
return 0;
}
在上述代码中,Base
类中的print
函数是虚函数,Derived
类覆盖了该虚函数。通过Base*
指针调用print
函数时,由于basePtr
实际指向Derived
对象,所以会调用Derived::print()
,体现了运行时多态。这里虚函数print
定义了可覆盖的接口,虚函数表记录了虚函数地址,而指针basePtr
实现了运行时根据对象实际类型调用正确的虚函数。