C++ 重载详解

C++ 重载详解

重载(Overloading)是C++中允许在同一作用域内使用相同名称但不同参数的函数或操作符的特性。C++支持两种主要的重载形式:函数重载和操作符重载。

一、函数重载(Function Overloading)

函数重载允许在同一作用域内定义多个同名函数,只要它们的参数列表不同即可。

1. 基本规则

  • 函数名相同
  • 参数列表必须不同(参数类型、数量或顺序)
  • 返回类型可以相同也可以不同(仅返回类型不同不足以构成重载)
void print(int i) {
    cout << "整数: " << i << endl;
}

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

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

2. 调用匹配规则

编译器根据以下顺序匹配最合适的重载函数:

  1. 精确匹配
  2. 提升转换(如char到int,float到double)
  3. 标准转换(如int到double,double到int)
  4. 用户定义的转换(如类中定义的转换操作符)

3. 注意事项

  • 默认参数可能导致重载歧义
  • const修饰符可以用于区分重载函数(当参数是指针或引用时)
  • 不能仅基于返回类型重载函数

二、操作符重载(Operator Overloading)

操作符重载允许为用户定义的类型(如类)赋予操作符特殊含义。

1. 基本语法

返回类型 operator 操作符(参数列表) {
    // 操作实现
}

2. 可重载的操作符

大多数C++操作符都可以重载,包括:

  • 算术运算符:+ - * / %
  • 关系运算符:== != < > <= >=
  • 逻辑运算符:&& || !
  • 位运算符:& | ^ ~ << >>
  • 赋值运算符:= += -= *= /= %= &= |= ^= <<= >>=
  • 其他:++ – -> , [] () new delete

不能重载的操作符:

  • 成员访问运算符:.
  • 成员指针运算符:.*
  • 作用域解析运算符:::
  • 条件运算符:?:
  • sizeof运算符

3. 成员函数与非成员函数重载

操作符可以作为类的成员函数或非成员函数重载:

// 作为成员函数
class Complex {
public:
    Complex operator+(const Complex& other) {
        return Complex(real + other.real, imag + other.imag);
    }
};

// 作为非成员函数
Complex operator+(const Complex& a, const Complex& b) {
    return Complex(a.real + b.real, a.imag + b.imag);
}

4. 特殊操作符重载示例

赋值运算符(=)
class MyString {
    char* str;
public:
    MyString& operator=(const MyString& other) {
        if (this != &other) {  // 防止自赋值
            delete[] str;      // 释放原有内存
            str = new char[strlen(other.str) + 1];
            strcpy(str, other.str);
        }
        return *this;          // 支持链式赋值
    }
};
下标运算符([])
class Array {
    int* data;
    int size;
public:
    int& operator[](int index) {
        if (index >= size || index < 0) {
            throw out_of_range("Index out of range");
        }
        return data[index];
    }
    
    const int& operator[](int index) const {
        if (index >= size || index < 0) {
            throw out_of_range("Index out of range");
        }
        return data[index];
    }
};
函数调用运算符(())
class Adder {
public:
    int operator()(int a, int b) {
        return a + b;
    }
};

Adder add;
int sum = add(3, 4);  // 调用函数对象
自增/自减运算符(++/–)
class Counter {
    int count;
public:
    // 前置++
    Counter& operator++() {
        ++count;
        return *this;
    }
    
    // 后置++
    Counter operator++(int) {
        Counter temp = *this;
        ++count;
        return temp;
    }
};

5. 输入/输出运算符重载(>>和<<)

通常作为非成员函数重载:

class Date {
    int day, month, year;
public:
    friend ostream& operator<<(ostream& os, const Date& dt);
    friend istream& operator>>(istream& is, Date& dt);
};

ostream& operator<<(ostream& os, const Date& dt) {
    os << dt.month << '/' << dt.day << '/' << dt.year;
    return os;
}

istream& operator>>(istream& is, Date& dt) {
    is >> dt.month >> dt.day >> dt.year;
    return is;
}

三、重载的注意事项

  1. 保持操作符的直观含义:重载操作符时应保持其原有语义,如+应该执行加法类操作
  2. 不能创建新操作符:只能重载现有操作符
  3. 操作符优先级不变:重载不会改变操作符的优先级
  4. 谨慎使用重载:过度或不恰当的重载会降低代码可读性
  5. 某些操作符必须作为成员函数重载:如=, [], (), ->必须作为成员函数重载

四、重载与多态

重载是编译时多态(静态多态)的一种形式,与运行时多态(动态多态,通过虚函数实现)不同。编译器在编译时根据参数类型决定调用哪个重载版本。

总结

C++重载提供了强大的表达能力,允许程序员为自定义类型提供自然的操作接口。合理使用重载可以显著提高代码的可读性和易用性,但应避免滥用导致代码难以理解。

你可能感兴趣的:(c++,c++,后端,青少年编程,算法)