MST

星途 面试题库

面试题:C++ 指针作为函数参数在多态场景下的应用

定义一个基类`Base`和一个派生类`Derived`,在`Base`类中有一个虚函数`print`。编写一个函数`process`,其参数为`Base*`指针类型,在函数内部调用`print`函数。在`main`函数中创建`Derived`类的对象,并将其指针传递给`process`函数,解释函数调用的过程以及虚函数表指针在这个过程中的作用。
48.8万 热度难度
编程语言C++

知识考点

AI 面试

面试题答案

一键面试

以下是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;
}

函数调用过程

  1. main函数中创建Derived类的对象derivedObj
  2. derivedObj的指针传递给process函数,process函数接受一个Base*类型的指针basePtr
  3. process函数内部,通过basePtr调用print函数。由于print函数是虚函数,C++的动态绑定机制会起作用。它会根据basePtr实际指向的对象类型(这里是Derived类型)来决定调用哪个版本的print函数。因此,最终调用的是Derived::print()

虚函数表指针的作用

  1. 当定义一个包含虚函数的类(如Base类)时,编译器会为该类创建一个虚函数表(vtable)。虚函数表是一个函数指针数组,其中每个元素指向类中虚函数的实际实现。
  2. 每个包含虚函数的类的对象都有一个虚函数表指针(vptr),这个指针指向该对象所属类的虚函数表。在对象构造时,vptr会被初始化,指向对应的虚函数表。
  3. 在上述代码中,Base类有一个虚函数print,所以Base类有一个虚函数表。Derived类继承自Base类并且重写了print函数,Derived类也有自己的虚函数表,该虚函数表中print函数的指针指向Derived::print的实现。
  4. Derived对象derivedObj创建时,其vptr被设置为指向Derived类的虚函数表。当process函数通过basePtr调用print函数时,实际上是通过basePtr所指向对象的vptr找到对应的虚函数表,然后在虚函数表中找到print函数的实际地址并调用,从而实现了动态绑定,确保调用的是Derived::print()而不是Base::print()