MST

星途 面试题库

面试题:C++抽象基类与多态性的深度结合

假设有一个抽象基类Shape,包含纯虚函数draw()。有Circle和Rectangle两个派生类继承自Shape并实现draw()函数。请编写一段代码,展示如何通过抽象基类指针或引用实现多态调用draw()函数,同时说明运行时多态在这种场景下是如何实现的,以及涉及到的底层机制(如虚函数表等)。
26.1万 热度难度
编程语言C++

知识考点

AI 面试

面试题答案

一键面试
#include <iostream>

// 抽象基类Shape
class Shape {
public:
    // 纯虚函数draw
    virtual void draw() const = 0;
};

// Circle派生类
class Circle : public Shape {
public:
    void draw() const override {
        std::cout << "Drawing a Circle." << std::endl;
    }
};

// Rectangle派生类
class Rectangle : public Shape {
public:
    void draw() const override {
        std::cout << "Drawing a Rectangle." << std::endl;
    }
};

int main() {
    // 通过抽象基类指针实现多态调用
    Shape* shapePtr1 = new Circle();
    shapePtr1->draw();
    delete shapePtr1;

    // 通过抽象基类引用实现多态调用
    Circle circle;
    Shape& shapeRef = circle;
    shapeRef.draw();

    return 0;
}
  1. 运行时多态的实现
    • 在上述代码中,通过Shape基类指针shapePtr1指向Circle对象,调用draw()函数时,实际执行的是Circle类中重写的draw()函数。同样,通过Shape基类引用shapeRef绑定到Circle对象,调用draw()函数也会执行Circle类中的draw()函数。这就是运行时多态,程序在运行时根据对象的实际类型来决定调用哪个类的虚函数。
  2. 底层机制 - 虚函数表
    • 当一个类包含虚函数(如Shape类中的draw()纯虚函数)时,编译器会为这个类生成一个虚函数表(vtable)。虚函数表是一个函数指针数组,每个元素是一个虚函数的地址。
    • 每个包含虚函数的类的对象都会有一个隐藏的指针(vptr),指向该类的虚函数表。当对象创建时,vptr 被初始化,指向该对象所属类的虚函数表。
    • 当通过基类指针或引用调用虚函数时,程序首先通过对象的vptr找到对应的虚函数表,然后根据虚函数表中函数指针的偏移量,找到并调用实际对象类型对应的虚函数。例如,当shapePtr1指向Circle对象时,shapePtr1所指向对象的vptr指向Circle类的虚函数表,在Circle类的虚函数表中draw()函数的实现地址被调用,从而实现了运行时多态。