C++函数重载与引用实战案例详解
作者:叒卮
函数重载:同名函数的 “差异化生存”
1. 概念定义
函数重载(Function Overloading)是 C++ 的重要特性,指在同一作用域内,允许存在多个同名函数,但要求这些函数的参数列表必须不同。
(参数个数、参数类型、参数顺序至少有一项不同)非常重要!!。
编译器会根据调用时传入的实参,自动匹配到对应的函数,实现 “一个函数名,多种功能” 的效果。
2. 典型案例分析
案例 1:参数个数不同的重载
#include <iostream> using namespace std; // 无参数版本 void print() { cout << "无参数调用" << endl; } // 1个int参数版本 void print(int a) { cout << "int参数:" << a << endl; } // 2个int参数版本 void print(int a, int b) { cout << "两个int参数:" << a << " " << b << endl; } int main() { print(); // 匹配无参数版本 print(10); // 匹配1个int参数版本 print(20, 30); // 匹配2个int参数版本 return 0; }
输出结果:
无参数调用
int参数:10
两个int参数:20 30
案例 2:参数类型不同的重载
#include <iostream> using namespace std; // int类型参数 int add(int a, int b) { return a + b; } // double类型参数 double add(double a, double b) { return a + b; } int main() { cout << "int加法:" << add(3, 5) << endl; // 匹配int版本,输出8 cout << "double加法:" << add(2.5, 4.5) << endl; // 匹配double版本,输出7.0 return 0; }
注意:仅返回值类型不同的函数,不能构成重载。例如int add(int a)和double add(int a),编译器无法通过调用语句(如add(10))区分,会报 “重定义” 错误。
案例 3:参数顺序不同的重载
#include <iostream> #include <string> using namespace std; // 先int后string void showInfo(int age, string name) { cout << "年龄:" << age << ",姓名:" << name << endl; } // 先string后int void showInfo(string name, int age) { cout << "姓名:" << name << ",年龄:" << age << endl; } int main() { showInfo(20, "张三"); // 匹配先int后string版本 showInfo("李四", 22); // 匹配先string后int版本 return 0; }
输出结果:
年龄:20,姓名:张三
姓名:李四,年龄:22
案例 4:多文件分离(声明与定义分离)
实际项目中,函数重载常涉及多文件拆分,需注意 “声明与定义的一致性”。
#ifndef FUNC_H #define FUNC_H // 防止头文件重复包含 // 声明3个重载函数 void calculate(int a); void calculate(double a); void calculate(int a, double b); #endif
#include "func.h" #include <iostream> using namespace std; void calculate(int a) { cout << "int参数计算:" << a * 2 << endl; } void calculate(double a) { cout << "double参数计算:" << a * 3 << endl; } void calculate(int a, double b) { cout << "int+double参数计算:" << a + b << endl; }
#include "func.h" int main() { calculate(5); // 匹配int版本,输出10 calculate(3.5); // 匹配double版本,输出10.5 calculate(2, 4.8); // 匹配int+double版本,输出6.8 return 0; }
编译运行:需将三个文件一起编译(如g++ main.cpp func.cpp -o test),确保声明的重载函数在定义文件中都有对应的实现,否则会报 “未定义引用” 错误。
3. 原理:为什么 C++ 支持,C 语言不支持?
核心原因在于编译器对函数名的 “修饰规则” 不同:
- C 语言:编译器会直接使用函数原名作为最终的 “符号名”(如函数add(int a, int b),符号名就是add)。若存在同名函数,符号名重复,链接阶段会报错,因此 C 语言不支持函数重载。
- C++ 语言:编译器会根据函数的参数列表对函数名进行 “修饰”(也称 “命名粉碎”,Name Mangling),生成唯一的符号名。例如:
- add(int a, int b)可能被修饰为_Z3addii(3表示函数名长度,ii表示两个 int 参数);
- add(double a, double b)可能被修饰为_Z3adddd。
不同重载函数的修饰后符号名不同,编译器和链接器能准确识别,因此 C++ 支持函数重载。
4.引用:变量的 “别名” 与权限控制
1. 概念定义
引用(Reference)是 C++ 引入的新特性,本质是变量的别名,它与原变量共享同一块内存空间,对引用的操作等同于对原变量的操作。语法格式为:类型& 引用名 = 原变量;。
注意:引用必须在定义时初始化,且初始化后不能再指向其他变量(与指针的核心区别)。
2. 基础操作:定义与使用
#include <iostream> using namespace std; int main() { int a = 10; int& ref_a = a; // 定义引用ref_a,作为a的别名 cout << "a的值:" << a << endl; // 输出10 cout << "ref_a的值:" << ref_a << endl; // 输出10(与a共享内存) ref_a = 20; // 操作引用,等同于修改a cout << "修改后a的值:" << a << endl; // 输出20 cout << "a的地址:" << &a << endl; // 输出a的地址(如0x7ffeefbff4ac) cout << "ref_a的地址:" << &ref_a << endl; // 输出相同地址(证明共享内存) return 0; }
3. 权限控制:放大、缩小与平移
引用的权限遵循 “不能放大原变量的权限” 原则,否则编译器会报错;权限缩小或平移是允许的。以下是典型案例:
案例 1:权限平移(同权限引用)
原变量是普通变量,引用也为普通引用,权限一致,合法。
int a = 10; int& ref_a = a; // 合法:普通变量→普通引用,权限平移
案例 2:权限缩小(原变量权限 > 引用权限)
原变量是普通变量(可读可写),引用为const引用(只读),权限缩小,合法。
int a = 10; const int& ref_a = a; // 合法:普通变量→const引用,权限缩小 ref_a = 20; // 错误:const引用只读,不能修改 a = 20; // 正确:原变量是普通变量,可修改(修改后ref_a的值也会变)
案例 3:权限放大(原变量权限 < 引用权限)
原变量是const变量(只读),引用为普通引用(可读可写),权限放大,非法。
const int a = 10; // a是const变量,只读 int& ref_a = a; // 错误:const变量→普通引用,权限放大,编译器报错
案例 4:临时变量的引用(易混淆点)
临时变量(如表达式结果、字面量)的权限是 “只读”,只能用const引用接收,否则会触发权限放大错误。
// 错误案例:临时变量→普通引用(权限放大) int& ref1 = 10; // 错误:10是临时变量,只读,普通引用无法接收 int& ref2 = 3 + 5; // 错误:3+5的结果是临时变量,只读 // 正确案例:临时变量→const引用(权限缩小) const int& ref3 = 10; // 合法:const引用可接收临时变量 const int& ref4 = 3 + 5; // 合法:临时变量值为8,ref4指向该临时变量
易错点总结
- 引用未初始化:定义引用时必须绑定原变量,否则报错。
错误:int& ref;(编译器提示 “引用必须初始化”)。
- 引用指向临时变量未加 const:如上述案例 4,临时变量只能用const引用接收,普通引用会触发权限放大错误。
- 混淆引用与指针:引用初始化后不能改指向,指针可以改指向;引用不需要解引用(*),指针需要。
错误:int a=10, b=20; int& ref=a; ref=&b;(试图让引用指向 b,编译器报错)。
- 数组引用的语法错误:数组引用需指定数组大小,语法格式为类型 (&引用名)[数组大小] = 原数组;。
错误:int arr[5] = {1,2,3,4,5}; int& ref_arr = arr;(未指定数组大小);
正确:int (&ref_arr)[5] = arr;。
总结
- 函数重载:C++ 通过 “参数列表不同” 实现同名函数的重载,核心原理是编译器对函数名的 “修饰规则”(根据参数列表生成唯一符号名),而 C 语言因无此修饰,不支持重载。
- 引用:本质是变量的别名,需初始化且不可改指向;权限控制遵循 “不能放大” 原则,临时变量需用const引用接收,避免权限相关错误。
到此这篇关于C++函数重载与引用的文章就介绍到这了,更多相关C++函数重载与引用内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!