c/c++中的多态(上)

1.了解多态

C 语言本身不支持原生多态,多态是 C++ 面向对象编程(OOP)的三大核心特性(封装、继承、多态)之一。

多态的本质:同一个接口,调用时表现出不同的行为(一个名字,多种形态)。

C++ 多态分为两大类,也是面试和开发中最核心的区分点:

1.静态多态(编译期多态):编译时就确定调用的函数

2.动态多态(运行期多态):运行时才确定调用的函数(C++ 多态的核心)

2.静态多态(早绑定)

在编译阶段,编译器就确定了函数的调用地址,也叫静态绑定。
特点:执行效率高,灵活性低。

三种实现形式:

1.函数重载

同一个作用域下,函数名相同,参数列表(个数、类型、顺序)不同,与返回值无关。

cpp 复制代码
#include <iostream>
using namespace std;

// 函数重载
void print(int a)    { cout << "整数:" << a << endl; }
void print(double b) { cout << "浮点数:" << b << endl; }
void print(string s) { cout << "字符串:" << s << endl; }

int main() {
    print(10);    // 编译期直接匹配 int 版本
    print(3.14);  // 编译期直接匹配 double 版本
    return 0;
}

2.运算符重载

对 C++ 原有运算符重新定义,适配自定义类型(如复数、类对象)。

3.模板(函数 / 类模板)

泛型编程,一套代码适配多种数据类型,编译期生成对应类型的函数。

cpp 复制代码
// 函数模板
template <typename T>
T add(T a, T b) {
    return a + b;
}

3.动态多态(晚绑定)

在运行阶段才确定函数的调用地址,也叫动态绑定。
特点:灵活性极高,是面向对象设计的核心,用于解耦代码。

实现条件(缺一不可):
1.存在 继承关系
2.基类定义 虚函数(virtual 关键字修饰)
3.派生类 重写 基类的虚函数
4.使用 基类指针 / 引用 指向派生类对象,调用虚函数

我们用「动物发声」来演示多态:

cpp 复制代码
#include <iostream>
using namespace std;

// 基类:动物
class Animal {
public:
    // 虚函数:动态多态的核心
    virtual void speak() {
        cout << "动物发出通用声音" << endl;
    }
};

// 派生类:狗(继承 Animal)
class Dog : public Animal {
public:
    // 重写基类的虚函数(override 关键字建议加上,用于校验)
    void speak() override {
        cout << "汪汪汪" << endl;
    }
};

// 派生类:猫(继承 Animal)
class Cat : public Animal {
public:
    void speak() override {
        cout << "喵喵喵" << endl;
    }
};

// 统一接口:接收基类指针,调用虚函数
void makeSound(Animal* animal) {
    animal->speak(); 
}

int main() {
    Dog dog;
    Cat cat;

    // 同一个接口 makeSound,传入不同对象,执行不同逻辑
    makeSound(&dog); // 输出:汪汪汪
    makeSound(&cat); // 输出:喵喵喵

    return 0;
}

✅ 这就是多态:接口不变,行为随对象类型自动变化。

3. 1核心概念
(1)虚函数

基类中用 virtual 修饰的成员函数,是动态多态的基础。

派生类重写虚函数时,virtual 关键字可写可不写,建议保留。

(2)重写(override)

派生类重新实现基类的虚函数,要求:

函数名、返回值、参数列表 完全一致(和重载完全不同)。

(3)纯虚函数 & 抽象类

纯虚函数:没有函数体,格式 virtual void speak() = 0;

抽象类:包含纯虚函数的类,不能创建对象,只能被继承

作用:强制派生类必须实现该函数(定义接口规范)

cpp 复制代码
// 抽象类(无法实例化)
class Animal {
public:
    // 纯虚函数
    virtual void speak() = 0;
};

4.重载 vs 重写

特性 函数重载(静态多态) 函数重写(动态多态)
作用域 同一个作用域 基类 + 派生类(继承关系)
函数签名 函数名同,参数不同 函数名 / 参数 / 返回值完全相同
关键字 virtual 必须有 virtual
绑定时机 编译期绑定 运行期绑定

5.C 语言模拟多态

C 没有类、继承、虚函数,只能用函数指针手动模拟多态(非原生):

cpp 复制代码
#include <stdio.h>

// 定义函数指针类型
typedef void (*SpeakFunc)();

// 动物结构体(模拟基类)
struct Animal {
    SpeakFunc speak; // 函数指针
};

// 狗的行为
void dogSpeak() { printf("汪汪汪\n"); }
// 猫的行为
void catSpeak() { printf("喵喵喵\n"); }

int main() {
    struct Animal dog = {dogSpeak};
    struct Animal cat = {catSpeak};

    dog.speak(); // 输出汪汪汪
    cat.speak(); // 输出喵喵喵
    return 0;
}

谢谢

相关推荐
大草原的小灰灰10 分钟前
Python基础语法
开发语言·python
无小道30 分钟前
C++——列表初始化
c++·列表初始化
blueSatchel1 小时前
c++action 编写(ros-humble)
c++·ros2
泡泡鱼(敲代码中)2 小时前
MySQL基础学习笔记:从数据模型到DDL全掌握
开发语言·数据库·笔记·学习·mysql
老赵的博客2 小时前
c++面试之从虚函数表到Rtti一次性讲清楚
c++·qt
潜创微科技3 小时前
IT6520:USB-C 转 MIPI 高集成控制器,DP 1.4a 转 MIPI 单芯片搞定 4K120 显示
c语言·开发语言·低延迟·掌机·联阳
Escalating_xu4 小时前
【System V 信号量】从 P/V 原语到 Builder 封装:写出可控、可清理的进程互斥组件
java·linux·开发语言·jvm
傲世仙尊4 小时前
System V 进程间通信详解:共享内存、消息队列与信号量(CSDN博客)
linux·开发语言·c++
cvby4 小时前
C++11
开发语言·c++
6Hzlia4 小时前
【Classic 150 刷题计划】 LeetCode 26. 删除有序数组中的重复项 | C++ 快慢双指针经典模板
c++·算法·leetcode