首页 > 试题广场 >

简述一下 C++ 中的多态

[问答题]

简述一下 C++ 中的多态

推荐

得分点

静态多态、动态多态、多态的实现原理、虚函数、虚函数表

参考答案

标准回答

在现实生活中,多态是同一个事物在不同场景下的多种形态。在面向对象中,多态是指通过基类的指针或者引用,在运行时动态调用实际绑定对象函数的行为,与之相对应的编译时绑定函数称为静态绑定。所以多态分为静态多态和动态多态。

  1. 静态多态

    静态多态是编译器在编译期间完成的,编译器会根据实参类型来选择调用合适的函数,如果有合适的函数就调用,没有的话就会发出警告或者报错。静态多态有函数重载、运算符重载、泛型编程等。

  2. 动态多态

    动态多态是在程序运行时根据基类的引用(指针)指向的对象来确定自己具体该调用哪一个类的虚函数。当父类指针(引用)指向 父类对象时,就调用父类中定义的虚函数;即当父类指针(引用)指向 子类对象时,就调用子类中定义的虚函数。

加分回答

  1. 动态多态行为的表现效果为:同样的调用语句在实际运行时有多种不同的表现形态。

  2. 实现动态多态的条件:

    • 要有继承关系
    • 要有虚函数重写(被 virtual 声明的函数叫虚函数)
    • 要有父类指针(父类引用)指向子类对象
  3. 动态多态的实现原理

    当类中声明虚函数时,编译器会在类中生成一个虚函数表,虚函数表是一个存储类虚函数指针的数据结构,
    虚函数表是由编译器自动生成与维护的。virtual 成员函数会被编译器放入虚函数表中,存在虚函数时,每个对象中都有一个指向虚函数表的指针(vptr 指针)。在多态调用时, vptr 指针就会根据这个对象在对应类的虚函数表中查找被调用的函数,从而找到函数的入口地址。

编辑于 2021-09-15 11:19:48 回复(0)
多态包括两种方式:重写和重载。
重写是指成员函数的名字不变,参数的类型数量顺序都不变,即只改变花括号内的函数体。
重载是指成员函数的名字不变,参数的类型数量顺序可以改变,函数体也可以改变,在调用时会根据参数的不同来选择调用哪一个函数。
发表于 2022-05-08 16:23:24 回复(0)

C++ 中的多态(Polymorphism)

多态(Polymorphism) 是面向对象编程(OOP)中的重要特性,它允许同一个接口(基类方法)在不同的对象上具有不同的行为。C++ 的多态可以分为 编译时多态(静态多态)运行时多态(动态多态) 两种。


1. 编译时多态(静态多态)

编译时多态是指在编译阶段就确定了调用哪个函数,主要包括:

① 函数重载(Function Overloading)

同名函数,参数不同(参数类型或数量不同)

#include <iostream>
using namespace std;

class Example {
public:
    void show(int x) { cout << "Integer: " << x << endl; }
    void show(double x) { cout << "Double: " << x << endl; }
    void show(string x) { cout << "String: " << x << endl; }
};

int main() {
    Example ex;
    ex.show(10);        // 调用 int 版本
    ex.show(3.14);      // 调用 double 版本
    ex.show("Hello");   // 调用 string 版本
    return 0;
}

② 运算符重载(Operator Overloading)

重载运算符,使其支持自定义数据类型

#include <iostream>
using namespace std;

class Complex {
public:
    int real, imag;
    Complex(int r, int i) : real(r), imag(i) {}

    // 重载 + 运算符
    Complex operator+(const Complex &c) {
        return Complex(real + c.real, imag + c.imag);
    }

    void display() { cout << real << " + " << imag << "i" << endl; }
};

int main() {
    Complex c1(3, 4), c2(1, 2);
    Complex c3 = c1 + c2; // 使用重载的 + 运算符
    c3.display();  // 输出:4 + 6i
    return 0;
}

③ 模板(Templates)

泛型编程,编译时确定类型

#include <iostream>
using namespace std;

template <typename T>
T add(T a, T b) {
    return a + b;
}

int main() {
    cout << add(3, 4) << endl;      // 7 (int)
    cout << add(3.5, 2.1) << endl;  // 5.6 (double)
    return 0;
}

2. 运行时多态(动态多态)

运行时多态是在程序运行阶段决定调用哪个函数,主要依赖于虚函数(virtual functions)动态绑定(dynamic binding)

① 继承与虚函数(Virtual Function)

基类指针/引用指向派生类对象,并调用重写的方法

#include <iostream>
using namespace std;

class Base {
public:
    virtual void show() { cout << "Base class" << endl; }  // 虚函数
};

class Derived : public Base {
public:
    void show() override { cout << "Derived class" << endl; }  // 重写基类方法
};

int main() {
    Base* ptr;
    Derived obj;
    ptr = &obj;

    ptr->show();  // 运行时确定,调用 Derived::show()
    return 0;
}

🔹 关键点

  • virtual关键字:告诉编译器该函数支持动态绑定(即运行时确定)。

  • 基类指针指向子类对象,调用的方法由子类重写版本决定。

② 纯虚函数(Pure Virtual Function)与抽象类

纯虚函数用于定义接口,强制子类必须实现该方法

#include <iostream>
using namespace std;

class Shape {
public:
    virtual void draw() = 0; // 纯虚函数
};

class Circle : public Shape {
public:
    void draw() override { cout << "Drawing Circle" << endl; }
};

int main() {
    // Shape obj; // ❌ 抽象类不能实例化
    Shape* shape = new Circle();
    shape->draw();  // 调用 Circle 的 draw()
    delete shape;
    return 0;
}

🔹 关键点

  • 含有纯虚函数的类称为抽象类,不能实例化

  • 派生类必须实现纯虚函数,否则仍然是抽象类


总结

多态类型 主要机制 绑定方式 示例
静态多态 函数重载、运算符重载、模板 编译时绑定 void show(int),operator+,template<typename T>
动态多态 继承 + 虚函数 运行时绑定 virtual void show(),override
  • 静态多态 提高程序效率(编译时决定调用),但灵活性较低。

  • 动态多态 提高程序扩展性(运行时决定调用),但有轻微性能开销。

应用场景

  • 静态多态:适用于编译时确定类型的情况,如重载操作、模板。

  • 动态多态:适用于需要运行时多态行为的场景,如 UI 组件绘制、策略模式等。

🚀 多态是面向对象编程的重要特性,使代码更具扩展性和可维护性!

发表于 2025-04-04 16:39:11 回复(0)