C++——重载

发布于:2025-03-28 ⋅ 阅读:(36) ⋅ 点赞:(0)

目录

一、函数重载

基本概念

函数重载的条件

编程示例

代码讲解

函数重载的注意事项

二、运算符重载

什么是运算符重载?

运算符重载的实质是什么?

运算符重载函数的写法

运算符重载的基本语法

可重载的运算符列表

基本原则

编程示例

代码解释

注意事项


一、函数重载

函数重载(Overloading)是C++中一个非常重要的特性,它允许在同一个作用域内定义多个同名函数,只要它们的参数列表不同即可

基本概念

在 C++ 里,函数重载指的是在同一个作用域内,能够存在一组函数名相同但参数列表不同的函数。这里所说的参数列表不同,包括参数类型、参数数量或者参数顺序的差异

当调用这些重载函数时,编译器会依据传入的实参情况,结合实参的类型和数量,来确定具体调用哪一个函数。比如,若调用时传入的实参类型和数量与某个重载函数的参数列表匹配,编译器就会调用该函数。

函数重载的条件

  1. 函数名必须相同

  2. 参数列表必须不同(如参数类型、参数数量或参数顺序不同)

  3. 返回类型可以相同也可以不同(仅返回类型不同不能构成重载)

编程示例

#include <iostream>

// 使用标准命名空间,这样就可以直接使用标准库中的对象和函数,无需加 std:: 前缀
using namespace std;

// 定义一个名为 func 的类,该类中包含了多个重载的 print 函数
class func
{
public:
    // 声明一个打印整数的函数,接受一个 int 类型的参数
    void print(int idata1);
    // 声明一个打印两个整数并计算它们之和的函数,接受两个 int 类型的参数
    void print(int idata1, int idata2);
    // 声明一个打印双精度浮点数的函数,接受一个 double 类型的参数
    void print(double ddata1);
    // 声明一个打印字符串的函数,接受一个字符数组(C 风格字符串)作为参数
    void print(char c[]);
};

// 类外定义 print 函数,实现打印一个整数的功能
void func::print(int idata1)
{
    // 输出传入的整数
    cout << "idata1:" << idata1 << endl;
}

// 类外定义 print 函数,实现打印两个整数并计算它们之和的功能
void func::print(int idata1, int idata2)
{
    // 输出传入的两个整数以及它们的和
    cout << "idata1:" << idata1 << ",idata2:" << idata2 << ",idata1 + idata2 = " << idata1 + idata2 << endl;
}

// 类外定义 print 函数,实现打印一个双精度浮点数的功能
void func::print(double ddata1)
{
    // 输出传入的双精度浮点数
    cout << "ddata1:" << ddata1 << endl;
}

// 类外定义 print 函数,实现打印一个字符串的功能
void func::print(char c[])
{
    // 输出传入的字符串
    cout << "字符串:" << c << endl;
}

int main()
{
    // 创建 func 类的一个对象 f1
    func f1;
    // 定义一个字符数组(C 风格字符串)并初始化为 "hello world"
    char cdata[] = "hello world";
    // 调用 print 函数,传入一个整数,此时会调用接受一个 int 参数的 print 函数
    f1.print(10);
    // 调用 print 函数,传入两个整数,此时会调用接受两个 int 参数的 print 函数
    f1.print(10,20);
    // 调用 print 函数,传入一个双精度浮点数,此时会调用接受一个 double 参数的 print 函数
    f1.print(3.14);
    // 调用 print 函数,传入一个字符数组,此时会调用接受一个字符数组参数的 print 函数
    f1.print(cdata);

    return 0;
}

代码讲解

  1. 类的定义
    • func 类中声明了四个重载的 print 函数,这些函数的名称相同,但参数列表不同。这是 C++ 函数重载的典型应用,通过函数重载可以使用相同的函数名来处理不同类型或数量的参数。
  2. 函数定义
    • 在类外对这四个 print 函数进行了定义,每个函数都有不同的实现逻辑,分别用于处理不同类型的输入。
  3. main 函数
    • 创建了 func 类的一个对象 f1
    • 定义了一个字符数组 cdata 并初始化为 "hello world"
    • 多次调用 f1 的 print 函数,每次传入不同类型或数量的参数。编译器会根据传入的实参自动选择合适的重载函数进行调用。例如,传入一个整数时,会调用接受一个 int 参数的 print 函数;传入两个整数时,会调用接受两个 int 参数的 print 函数,以此类推。

函数重载的注意事项

返回类型不同不构成重载

int func(int a);         // 正确
double func(int a);      // 错误,仅返回类型不同

默认参数可能导致重载歧义

void func(int a);
void func(int a, int b = 0); // (默认b=0)

func(10);  // 编译器无法确定调用哪个函数

const修饰符可以构成重载

  • 对于指针或引用参数,const可以构成重载

  • 对于值参数,const不能构成重载

// 可以构成重载
void func(int &a);
void func(const int &a);

// 不能构成重载
void func(int a);
void func(const int a);  // 重复声明

函数重载与作用域

  • 在不同作用域中的同名函数不构成重载

  • 派生类中的同名函数会隐藏基类中的同名函数

二、运算符重载

什么是运算符重载?

运算符重载:赋予运算符具有操作自定义类型数据功能

运算符重载的实质是什么?

运算符重载的实质本身就是函数调用

运算符重载函数的写法

函数返回值类型   函数名(函数参数)

  • 函数返回值的类型 :运算完成后的值决定的
  • 函数名                   :operator 加上重载运算符组成函数名,例如:operator+
  • 参数列表               :看运算符的操作数,具体参数个数需要看函数的形式(成员函数或友元函数)
  • 函数体                   :写运算符具体想要的操作

运算符重载的基本语法

返回类型 operator运算符(参数列表) {
    // 实现代码
}

可重载的运算符列表

可以重载的运算符

+ - * / % ^ & | ~ ! = < > 
+= -= *= /= %= ^= &= |= 
<< >> >>= <<= == != <= >= 
&& || ++ -- , ->* -> () [] 
new new[] delete delete[]

不能重载的运算符

. .* :: ?: sizeof typeid

基本原则

1. 不可以创建新的运算符:只能重载已经存在的运算符。

2. 至少有一个操作数是用户定义的类型:不能重载两个基本类型的运算符。

3. 不能更改运算符的优先级:重载的运算符保持其原有的优先级和结合性。

编程示例

这个示例创建了三个对象:p1、p2、p3;分别对 p1、p2 这两个对象的成员变量赋值,p3 的值等于p1 + p2。运算符 + 只能对基本数据类型进行计算,不能对自定义类型进行计算。所以我们需要重载运算符 + ,才能进行对象 p1 和 p2 进行计算,将 p1 + p2 的运算结果存储在对象 p3。

#include <iostream>

using namespace std;

// 定义一个名为coord的类,表示二维坐标点
class coord
{
public:
    int x;  // x坐标
    int y;  // y坐标

    // 声明重载大于运算符(>)的成员函数
    bool operator>(coord data);
};

// 实现重载的大于运算符
// 比较规则:比较两个坐标点的x和y之和
bool coord::operator>(coord data)
{
    return ((x + y) > (data.x + data.y));
}

int main()
{
    // 创建第一个坐标点p1
    coord p1;
    p1.x = 9;  // 设置p1的x坐标为9
    p1.y = 6;  // 设置p1的y坐标为6

    // 创建第二个坐标点p2
    coord p2;
    p2.x = 5;  // 设置p2的x坐标为5
    p2.y = 6;  // 设置p2的y坐标为6

    // 类成员函数重载,参数个数等于操作数减一
    // 使用重载的>运算符比较两个坐标点,实际比较的是(9+6)和(5+6),即15和11
    if( p1 > p2 ) // p1 > p2(隐式调用) 等价于 p1.operator>(p2)(显示调用)
    {
        cout << "p1大于p2" << endl;  // 会输出这个结果
    }
    else
    {
        cout << "p2大于p1" << endl;
    }

    return 0;
}

代码解释

上面代码的重载函数是成员函数形式,当运算符重载作为成员函数时,它已经有一个隐含的参数——调用对象本身(this指针)。所以:

  1. 调用对象:运算符左侧的对象(p1)是调用者,通过this指针隐式传递

  2. 参数对象:运算符右侧的对象(p2)作为显式参数传递

注意事项

  • 一致性:重载的运算符应与其原始意图和常见用法保持一致。例如, + 运算符通常应该实现加法,而不是其他意外的操作。
  • 复杂性:过度使用运算符重载可能导致代码难以理解和维护。确保它们的使用直观且合理。 运算符重载是C++中提高代码可读性和表达力的强大工具,但需要谨慎使用,以保证代码的清晰性和维护性。