面试题答案
一键面试以下是C++代码实现:
#include <iostream>
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;
}
};
void process(Base* basePtr) {
basePtr->print();
}
int main() {
Derived derivedObj;
process(&derivedObj);
return 0;
}
函数调用过程
- 在
main
函数中创建Derived
类的对象derivedObj
。 - 将
derivedObj
的指针传递给process
函数,process
函数接受一个Base*
类型的指针basePtr
。 - 在
process
函数内部,通过basePtr
调用print
函数。由于print
函数是虚函数,C++的动态绑定机制会起作用。它会根据basePtr
实际指向的对象类型(这里是Derived
类型)来决定调用哪个版本的print
函数。因此,最终调用的是Derived::print()
。
虚函数表指针的作用
- 当定义一个包含虚函数的类(如
Base
类)时,编译器会为该类创建一个虚函数表(vtable)。虚函数表是一个函数指针数组,其中每个元素指向类中虚函数的实际实现。 - 每个包含虚函数的类的对象都有一个虚函数表指针(vptr),这个指针指向该对象所属类的虚函数表。在对象构造时,vptr会被初始化,指向对应的虚函数表。
- 在上述代码中,
Base
类有一个虚函数print
,所以Base
类有一个虚函数表。Derived
类继承自Base
类并且重写了print
函数,Derived
类也有自己的虚函数表,该虚函数表中print
函数的指针指向Derived::print
的实现。 - 当
Derived
对象derivedObj
创建时,其vptr被设置为指向Derived
类的虚函数表。当process
函数通过basePtr
调用print
函数时,实际上是通过basePtr
所指向对象的vptr找到对应的虚函数表,然后在虚函数表中找到print
函数的实际地址并调用,从而实现了动态绑定,确保调用的是Derived::print()
而不是Base::print()
。