通俗讲解 初学者一文看懂!虚函数、函数重载、重写的区别

本文涉及的产品
函数计算FC,每月15万CU 3个月
容器镜像服务 ACR,镜像仓库100个 不限时长
应用实时监控服务-可观测链路OpenTelemetry版,每月50GB免费额度
简介: 函数重载允许在同一作用域内定义同名但参数列表不同的函数,提高代码灵活性和可读性,避免命名冲突。通过参数类型自动选择合适版本,如C++中的`print()`可处理整数、浮点数和字符串。虚函数实现运行时多态,基类指针调用时调用实际对象的版本。抽象类至少有一个纯虚函数,不能实例化,用于定义接口规范。抽象类和纯虚函数是构建多态和继承体系的基础,提供接口标准,减少代码冗余,增强代码清晰性和可维护性。

函数重载:多面手的编程艺术

What - 函数重载是什么?

函数重载是C++中一种允许在同一个作用域内定义多个同名函数的特性,只要这些函数的参数列表(参数的数量、类型或顺序)不同即可。这种机制极大地增强了代码的灵活性和可读性,使得开发者能以一致的方式调用功能相似但操作数据类型不同的函数。

Why - 为什么要用函数重载?

函数重载的存在解决了命名冲突的问题,避免了为类似功能的函数赋予冗长且难以记忆的名字。没有函数重载,我们可能需要为每个数据类型创建一个独立的函数,比如print_int()print_float()print_char()等,这不仅增加了编码负担,也降低了代码的整洁度和可维护性。通过重载,我们能使用统一的函数名,如print(),通过参数的不同自动调用合适的函数版本。

How - 如何使用函数重载?

函数重载的使用非常直观,只需要在同一个作用域下定义具有相同函数名但参数列表不同的函数即可。例如:

Cpp

#include <iostream>
using namespace std;

void print(int x) {
    cout << "打印整数:" << x << endl;
}

void print(double x) {
    cout << "打印浮点数:" << x << endl;
}

void print(string s) {
    cout << "打印字符串:" << s << endl;
}

int main() {
    print(42);          // 调用第一个print()函数
    print(3.14);        // 调用第二个print()函数
    print("Hello!");    // 调用第三个print()函数
    return 0;
}

在这段代码中,我们定义了三个print()函数,分别处理整数、浮点数和字符串。当我们在main()函数中调用print()时,编译器会根据传递给函数的参数类型自动选择正确的函数版本执行。


虚函数:动态多态的基石

虚函数是什么?

虚函数是C++中实现多态的关键机制,允许派生类重写基类中的函数,从而实现运行时的多态性。当通过基类的指针或引用调用虚函数时,实际上调用的是指向的对象所属类的版本,而不是基类中的版本。

多态是什么?

多态是面向对象编程的核心概念,允许同一操作作用于不同类型的对象上,产生不同的行为。这在C++中主要通过虚函数实现。

虚函数的格式与条件

声明虚函数的基本语法如下:

Cpp

1virtual <返回类型> <函数名>(<参数列表>);

要声明一个虚函数,只需在其声明前加上virtual关键字。虚函数必须是非静态成员函数,且可以在派生类中被重写。

抽象类

带有至少一个纯虚函数的类被称为抽象类。抽象类无法实例化,主要用于作为其他类的基类,定义接口规范而不提供具体实现。例如:

Cpp

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

class Dog : public Animal {
public:
    void speak() override {
        cout << "汪汪!" << endl;
    }
};

在这个例子中,Animal类是一个抽象类,它定义了speak()接口,但没有提供实现。Dog类继承自Animal并实现了speak()方法。




抽象类与纯虚函数:构建多态的基石

抽象类概述

抽象类是一种特殊的类,设计目的是为了提供一个高层次的抽象模板,它不允许直接实例化对象。在抽象类中,至少包含一个未被实现的纯虚函数,这样的设计使得抽象类成为继承体系中的一个关键节点,为所有派生类提供了一个通用的接口框架。

抽象类的作用

  • 提供接口规范:抽象类定义了一组子类必须遵循的接口,确保所有派生类具备相同的行为集。
  • 避免重复编码:通过将共享属性和行为封装在抽象类中,减少了代码冗余,提高了代码复用性。
  • 促进代码清晰性和可维护性:抽象类使得继承体系更加清晰,便于理解和维护。

纯虚函数与抽象类

纯虚函数的声明形式为virtual void function_name() = 0;,它告知编译器该函数必须在派生类中被实现。如果派生类未能实现抽象基类中的纯虚函数,那么该派生类也将被视为抽象类,不可实例化。

示例:动物王国

假设我们需要设计一个动物类的继承体系,我们可以从一个抽象类Animal开始:

Cpp

class Animal {
public:
    virtual void eat() = 0; // 纯虚函数,定义吃的行为
    virtual ~Animal() {}    // 析构函数,虚析构确保派生类对象的正确销毁
};

这个Animal类是抽象的,因为它包含了一个纯虚函数eat()。接下来,我们可以定义具体的动物类,比如DogHuman

Cpp

class Dog : public Animal {
public:
    void eat() override { /* 实现狗吃东西的行为 */ }
};

class Human : public Animal {
public:
    void eat() override { /* 实现人类吃东西的行为 */ }
};

虚函数的作用

虚函数的主要作用是实现多态,使得通过基类指针或引用调用虚函数时,能够动态地绑定到派生类的具体实现,而非静态绑定到基类的默认实现。

解决二义性

在多继承场景下,如果两个基类中有同名成员,可能会导致二义性问题。解决这一问题的常用方法是显式地使用作用域解析运算符::来指定调用哪个基类的成员。

例如,假设ClassAClassB都有成员函数function(), ClassC继承自ClassAClassB:

Cpp

class ClassA {
public:
    void function() { /* ClassA 的 function 实现 */ }
};

class ClassB {
public:
    void function() { /* ClassB 的 function 实现 */ }
};

class ClassC : public ClassA, public ClassB {
public:
    void call_function() {
        ClassA::function(); // 显式调用 ClassA 的 function
        ClassB::function(); // 显式调用 ClassB 的 function
    }
};

总结

抽象类与纯虚函数是C++中实现多态的重要机制,通过定义抽象类和纯虚函数,我们可以构建出高度可扩展和可维护的代码结构。抽象类提供了一个接口规范,确保所有派生类都遵循相同的约定,而纯虚函数则强制派生类必须实现特定的行为。掌握这些概念是深入理解C++面向对象编程的关键。

相关文章
|
自然语言处理 安全 C++
【C++ 格式化输出 】C++20 现代C++格式化:拥抱std--format简化你的代码
【C++ 格式化输出 】C++20 现代C++格式化:拥抱std--format简化你的代码
8816 4
|
Java C++ C语言
UE4/5动画蓝图中Additive Animations讲解
UE4/5动画蓝图中Additive Animations讲解
868 0
UE4/5动画蓝图中Additive Animations讲解
|
存储
CocosCreator3.8研究笔记(十一)CocosCreator Prefab(预制件)理解
CocosCreator3.8研究笔记(十一)CocosCreator Prefab(预制件)理解
982 0
|
测试技术
QT --- VS2017+Qt5.12 编译报错【E2512 功能测试宏的参数必须是简单标识符 】的解决方法
QT --- VS2017+Qt5.12 编译报错【E2512 功能测试宏的参数必须是简单标识符 】的解决方法
1049 0
|
Web App开发 JSON 测试技术
精通Postman接口测试:关联技术与自动化实践指南
这篇文章详细介绍了如何使用Postman进行接口测试,包括关联技术、自动化实践,以及如何通过环境变量和全局变量解决接口之间的关联性问题。
382 0
精通Postman接口测试:关联技术与自动化实践指南
《QT从基础到进阶·六》布局及布局中的小部件排列
《QT从基础到进阶·六》布局及布局中的小部件排列
321 0
|
存储 缓存 监控
Linux内存管理:理解正常波动背后的机制
Linux内存管理:理解正常波动背后的机制
361 0
|
人工智能 JavaScript 开发工具
【完全免费】VS Code 最好用的 12 款 AI 代码提示插件!!!
🎉 探索12款免费VSCode AI代码提示插件:Codeium、Codegeex、CodeFuse、TONGYI Lingma、Comate、iFlyCode、Fitten Code、Bito AI、Mintlify Doc Writer、Kodezi AI、aiXcoder、IntelliCode。这些插件提供智能补全、代码生成、注释、优化,支持多种语言,提升编程效率!🚀👩‍💻👨‍💻
16497 0
|
消息中间件 前端开发 算法
【十七】RabbitMQ基础篇(延迟队列和死信队列实战)
【十七】RabbitMQ基础篇(延迟队列和死信队列实战)
249 1
|
JavaScript
vue3如何通过ref属性获取界面上的元素?
vue3如何通过ref属性获取界面上的元素?
251 0