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

简介: 函数重载允许在同一作用域内定义同名但参数列表不同的函数,提高代码灵活性和可读性,避免命名冲突。通过参数类型自动选择合适版本,如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++面向对象编程的关键。

相关文章
|
负载均衡 Ubuntu 应用服务中间件
|
存储 编译器 C++
【c++】多态(多态的概念及实现、虚函数重写、纯虚函数和抽象类、虚函数表、多态的实现过程)
本文介绍了面向对象编程中的多态特性,涵盖其概念、实现条件及原理。多态指“一个接口,多种实现”,通过基类指针或引用来调用不同派生类的重写虚函数,实现运行时多态。文中详细解释了虚函数、虚函数表(vtable)、纯虚函数与抽象类的概念,并通过代码示例展示了多态的具体应用。此外,还讨论了动态绑定和静态绑定的区别,帮助读者深入理解多态机制。最后总结了多态在编程中的重要性和应用场景。 文章结构清晰,从基础到深入,适合初学者和有一定基础的开发者学习。如果你觉得内容有帮助,请点赞支持。 ❤❤❤
1752 1
|
9月前
|
存储 编解码 JSON
PowerToys微软最强工具箱软件集!好用的Windows增强工具箱,降低内存和存储占用
Microsoft PowerToys是微软官方推出的免费开源工具集,专为Win10/11设计,集成20+实用功能,如高级粘贴、颜色拾取、窗口布局管理(FancyZones)、文本提取、屏幕缩放标注等,全面提升办公效率,支持开发者、设计师等高效操作,模块化自由配置,堪称Windows效率神器。
1119 7
|
11月前
|
人工智能 监控 大数据
AR眼镜在警务安防的应用方案
针对当前社会治安防控难题,基于阿法龙XR云平台打造的云眼AI警务模块,融合AR与AI技术,构建“感知-分析-指挥-执行”一体化防控体系。通过AR智能眼镜实现人脸识别、车牌识别、人证比对、远程调度、执法记录等功能,提升执法效率与智能化水平,助力警务模式转型升级。
|
机器学习/深度学习 人工智能 编解码
【AI系统】MobileNet 系列
本文详细介绍 MobileNet 系列模型,重点探讨其轻量化设计原则。从 MobileNetV1 开始,通过深度可分离卷积和宽度乘数减少参数量,实现低延迟、低功耗。后续版本 V2、V3、V4 逐步引入线性瓶颈、逆残差、Squeeze-and-Excitation 模块、新型激活函数 h-swish、NAS 搜索等技术,持续优化性能。特别是 MobileNetV4,通过通用倒瓶颈(UIB)和 Mobile MQA 技术,大幅提升模型效率,达到硬件无关的 Pareto 最优。文章结合最新深度学习技术,全面解析各版本的改进与设计思路。
5678 8
|
存储 网络协议 机器人
车载以太网权威指南阅读笔记
车载以太网权威指南阅读笔记
|
Web App开发 JSON 测试技术
精通Postman接口测试:关联技术与自动化实践指南
这篇文章详细介绍了如何使用Postman进行接口测试,包括关联技术、自动化实践,以及如何通过环境变量和全局变量解决接口之间的关联性问题。
881 0
精通Postman接口测试:关联技术与自动化实践指南
在Linux中,Rsync 同步时,如果要同步的源中有软连接,如何把软连接的目标文件或者目录同步?
在Linux中,Rsync 同步时,如果要同步的源中有软连接,如何把软连接的目标文件或者目录同步?
|
Go 网络架构 网络协议
UDP 单播、广播和多播
阅读目录(Content) 一、UDP广播  二、UDP多播 1、多播(组播)的概念 2、广域网的多播 三、UDP广播与单播 广播与单播的比较      使用UDP协议进行信息的传输之前不需要建议连接。
4702 0
|
小程序 前端开发 Java
基于微信小程序的鲜花预定系统的设计与实现
基于微信小程序的鲜花预定系统的设计与实现
886 0