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;
}

谢谢

相关推荐
彷徨而立1 小时前
【C++】介绍 std::ifstream 输入文件流
开发语言·c++
罗超驿1 小时前
13.JavaScript 新手入门指南:语法、变量、流程控制全解析
开发语言·javascript
MC皮蛋侠客1 小时前
C++17 多线程系列(十):多线程性能优化——从测量到调优
c++·多线程
yingjie1101 小时前
Scanpy vs Seurat 深度对比:Python 与 R 的单细胞分析框架谁更强?
开发语言·python·r语言·生物信息学·单细胞转录组·seurat·scanpy
程序大视界2 小时前
【C++ 从基础到项目实战】C++(六):拷贝控制——浅拷贝与深拷贝,兼谈智能指针
开发语言·c++·cpp
luck_bor2 小时前
IO流知识点笔记
java·开发语言·笔记
程序大视界2 小时前
【Python系列课程】Pandas(四):数据统计与排序——describe、sort_values、sample
开发语言·python·pandas
KWTXX2 小时前
使用matlab官网的skills调用claude-待完成
开发语言·matlab