多态的概念理解

一、多态的概念

多态(Polymorphism)一词源于希腊语,意为”多种形态”。在面向对象程序设计中,多态是对人类思维方式的一种直接模拟。

比如我们日常生活中说的”打球”的”打”,就是一个抽象的信息,具有多种含义。打篮球、打排球、打羽毛球,都使用了”打”来表示参与某种球类运动,但每种运动的具体规则、动作和器材却相差甚远。实际上,这就是对多种运动行为的抽象——用一个统一的词表达不同的具体操作。

在 C++ 中,多态性是指一段程序能够处理多种类型对象的能力。同一个操作作用于不同的对象,可以产生不同的执行结果。

二、多态的通俗理解

现实场景统一操作不同对象的不同表现
打球“打”篮球:运球投篮 / 排球:垫球扣球 / 羽毛球:挥拍扣杀
叫声“叫”狗:”汪汪” / 猫:”喵喵” / 鸭子:”嘎嘎”
绘图“draw”圆形:画圆 / 矩形:画矩形 / 三角形:画三角形
移动“move”汽车:四个轮子转 / 船:螺旋桨推 / 飞机:喷气引擎

核心思想:对外提供统一的接口,内部执行不同的实现。

三、C++ 中多态的四种实现形式

C++ 中多态可以通过四种形式来实现:

多态形式说明典型例子备注
强制多态通过强制类型转换实现(double)5 / 2即类型转换多态
重载多态通过函数重载或运算符重载实现Add(int, int) 与 Add(float, float)编译时确定
类型参数化多态通过函数模板或类模板实现template<typename T> T max(T a, T b)编译时确定
包含多态通过基类指针或引用调用虚函数实现基类指针指向派生类对象,调用虚函数运行时确定

前三种属于编译时多态(静态多态),在编译阶段就确定了调用哪个函数。包含多态属于运行时多态(动态多态),在程序运行阶段才根据对象的实际类型确定调用哪个函数。

四、代码示例

以下代码演示了不同形式的多态:

#include <iostream>
#include <string>
using namespace std;

// ===== 1. 重载多态(函数重载)=====
int add(int a, int b)
{
    cout << "调用 add(int, int): ";
    return a + b;
}

double add(double a, double b)
{
    cout << "调用 add(double, double): ";
    return a + b;
}

// ===== 2. 包含多态(虚函数,运行时多态)=====
class Animal
{
public:
    virtual void speak()    // 虚函数
    {
        cout << "动物发出声音" << endl;
    }
};

class Dog : public Animal
{
public:
    void speak() override   // 重写基类虚函数
    {
        cout << "狗叫:汪汪" << endl;
    }
};

class Cat : public Animal
{
public:
    void speak() override
    {
        cout << "猫叫:喵喵" << endl;
    }
};

class Duck : public Animal
{
public:
    void speak() override
    {
        cout << "鸭子叫:嘎嘎" << endl;
    }
};

// ===== 3. 类型参数化多态(函数模板)=====
template <typename T>
T getMax(T a, T b)
{
    return (a > b) ? a : b;
}

// ===== 4. 强制多态(类型转换)=====
void printValue(int x)
{
    cout << "整数值:" << x << endl;
}

int main()
{
    // ---- 重载多态 ----
    cout << "===== 重载多态 =====" << endl;
    cout << add(1, 2) << endl;
    cout << add(1.5, 2.5) << endl;
    cout << endl;

    // ---- 包含多态 ----
    cout << "===== 包含多态(运行时)=====" << endl;
    Animal* ptr;

    Dog dog;
    Cat cat;
    Duck duck;

    ptr = &dog;
    ptr->speak();          // 实际调用 Dog::speak()

    ptr = &cat;
    ptr->speak();          // 实际调用 Cat::speak()

    ptr = &duck;
    ptr->speak();          // 实际调用 Duck::speak()
    cout << endl;

    // ---- 类型参数化多态 ----
    cout << "===== 类型参数化多态(模板)=====" << endl;
    cout << "max(10, 20) = " << getMax(10, 20) << endl;
    cout << "max(3.14, 2.71) = " << getMax(3.14, 2.71) << endl;
    cout << "max('x', 'a') = " << getMax('x', 'a') << endl;
    cout << endl;

    // ---- 强制多态 ----
    cout << "===== 强制多态 =====" << endl;
    double d = 3.7;
    printValue((int)d);    // 强制类型转换,调用 printValue(int)

    return 0;
}

分析:

  • 重载多态:add(1, 2) 调用 add(int, int),add(1.5, 2.5) 调用 add(double, double),编译器根据实参类型在编译时确定调用哪个版本。
  • 包含多态:Animal* 指针可以指向 Dog、Cat、Duck 对象,调用 speak() 时,程序在运行时根据实际指向的对象类型决定调用哪个函数。同一行代码 ptr->speak() 产生了三种不同的输出。
  • 类型参数化多态:getMax 是一个函数模板,可以处理 int、double、char 等多种类型,编译器根据传入的参数类型自动生成对应版本。
  • 强制多态:通过 (int)d 将 double 强制转换为 int,使 printValue 能接受 double 类型的参数。

五、编译时多态 vs 运行时多态

特性编译时多态(静态)运行时多态(动态)
确定时机编译阶段运行阶段
实现方式函数重载、模板、强制类型转换虚函数 + 基类指针/引用
性能无额外开销有虚函数表查找开销
灵活性编译后固定运行时可动态切换
典型应用运算符重载、swap 模板插件架构、回调机制、框架设计

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注