C++ 函数全解
目录弁言
1. 函数的定义
1.1 根本语法
1.2 示例
1.3 函数声明与定义
2. 函数的调用
2.1 根本调用
2.2 函数调用的执行过程
2.3 函数调用的栈帧
3. 参数传递
3.1 按值传递
3.2 按引用传递
3.3 按指针传递
3.4 默认参数
3.5 可变参数
3.6 常量引用参数
4. 返回值
4.1 根本返回值
4.2 多返回值
4.3 返回引用
4.4 返回指针
5. 函数重载
5.1 根本概念
5.2 重载规则
5.3 重载示例
6. 内联函数
6.1 根本概念
6.2 使用场景
6.3 内联函数的限定
7. 递归函数
7.1 根本概念
7.2 递归优化
7.3 递归示例:斐波那契数列
8. 函数指针
8.1 根本概念
8.2 函数指针数组
8.3 函数指针作为参数
8.4 函数指针的范例别名
9. Lambda 函数
9.1 根本概念
9.2 Lambda 的捕获列表
9.3 Lambda 作为参数
9.4 Lambda 的捕获方式
10. 模板函数
10.1 根本概念
10.2 模板特化
10.3 模板参数
11. 函数对象
11.1 根本概念
11.2 函数对象的捕获
11.3 函数对象的机动性
12. 函数的高级用法
12.1 函数模板的默认参数
12.2 函数模板的显式特化
12.3 函数模板的部分特化
13. 函数的最佳实践
13.1 函数的命名
13.2 函数的长度
13.3 函数的参数
13.4 函数的返回值
13.5 函数的错误处置惩罚
14. 应用实例
15. 总结
弁言
在C++编程中,函数是步调的根本构建块之一。函数可以将代码组织成可重用的模块,提高代码的可读性和可维护性。本文将详细介绍C++函数的各种特性,包罗函数的定义、调用、参数传递、返回值、重载、内联函数、递归函数、函数指针、Lambda 函数、模板函数和函数对象。
1. 函数的定义
1.1 根本语法
函数的根本定义语法如下:
返回类型 函数名(参数列表) {
// 函数体
}
[*]返回范例:函数执行后返回的数据范例。假如函数不返回任何值,使用 void。
[*]函数名:函数的名称,用于调用函数。
[*]参数列表:函数担当的参数,可以为空。
[*]函数体:函数的具体实现。
1.2 示例
int add(int a, int b) {
return a + b;
} 1.3 函数声明与定义
函数可以在声明后定义,也可以在定义时声明。声明通常放在头文件中,定义放在源文件中。
// 声明int add(int a, int b);// 定义int add(int a, int b) {
return a + b;
} 2. 函数的调用
2.1 根本调用
函数调用时,需要提供与参数列表匹配的参数。
int result = add(3, 5); // result = 8 2.2 函数调用的执行过程
[*]参数传递:将实际参数传递给函数的形参。
[*]执行函数体:执行函数体中的代码。
[*]返回结果:函数执行完毕后,返回结果(假如有)。
2.3 函数调用的栈帧
每次调用函数时,体系会在栈上为该函数分配一个栈帧,用于存储函数的局部变量和参数。函数调用结束后,栈帧被开释。
3. 参数传递
3.1 按值传递
按值传递是指将实际参数的值复制给形参。形参的任何修改都不会影响实际参数。
void modifyValue(int x) {
x = 10;
}
int main() {
int a = 5;
modifyValue(a);
std::cout << a << std::endl; // 输出 5
return 0;
} 3.2 按引用传递
按引用传递是指将实际参数的引用传递给形参。形参的任何修改都会影响实际参数。
void modifyValue(int& x) {
x = 10;
}
int main() {
int a = 5;
modifyValue(a);
std::cout << a << std::endl; // 输出 10
return 0;
} 3.3 按指针传递
按指针传递是指将实际参数的地点传递给形参。通过指针可以修改实际参数。
void modifyValue(int* x) {
*x = 10;
}
int main() {
int a = 5;
modifyValue(&a);
std::cout << a << std::endl; // 输出 10
return 0;
} 3.4 默认参数
默认参数是指在函数声明中为参数提供默认值。假如调用函数时没有提供相应的参数,将使用默认值。
void greet(std::string name, std::string greeting = "Hello") {
std::cout << greeting << ", " << name << "!" << std::endl;
}
int main() {
greet("Alice"); // 输出 "Hello, Alice!"
greet("Bob", "Hi"); // 输出 "Hi, Bob!"
return 0;
} 3.5 可变参数
可变参数函数可以担当不同数量的参数。C++11 引入了 std::initializer_list 和变长模板来实现可变参数。
void printNumbers(std::initializer_list<int> numbers) {
for (int num : numbers) {
std::cout << num << " ";
}
std::cout << std::endl;
}
int main() {
printNumbers({1, 2, 3, 4, 5}); // 输出 "1 2 3 4 5 "
return 0;
} 3.6 常量引用参数
常量引用参数可以防止函数修改传入的参数。
void print(const std::string& message) {
std::cout << message << std::endl;
}
int main() {
std::string msg = "Hello, World!";
print(msg); // 输出 "Hello, World!"
return 0;
} 4. 返回值
4.1 根本返回值
函数可以返回一个值,返回值的范例在函数声明时指定。
int add(int a, int b) {
return a + b;
} 4.2 多返回值
C++ 不直接支持多返回值,但可以通过返回布局体或元组来实现。
#include <tuple>
std::tuple<int, int> addAndSubtract(int a, int b) {
return std::make_tuple(a + b, a - b);
}
int main() {
int sum, diff;
std::tie(sum, diff) = addAndSubtract(10, 5);
std::cout << "Sum: " << sum << ", Difference: " << diff << std::endl; // 输出 "Sum: 15, Difference: 5"
return 0;
} 4.3 返回引用
函数可以返回引用,答应调用者修改返回的值。
int& getMax(int& a, int& b) {
return (a > b) ? a : b;
}
int main() {
int x = 10, y = 20;
getMax(x, y) = 30;
std::cout << "x: " << x << ", y: " << y << std::endl; // 输出 "x: 10, y: 30"
return 0;
} 4.4 返回指针
函数可以返回指针,但需要留意指针的有效性。
int* createArray(int size) {
int* arr = new int;
for (int i = 0; i < size; ++i) {
arr = i;
}
return arr;
}
int main() {
int* arr = createArray(5);
for (int i = 0; i < 5; ++i) {
std::cout << arr << " ";
}
delete[] arr; // 释放内存
return 0;
} 5. 函数重载
5.1 根本概念
函数重载是指在同一个作用域中定义多个同名函数,但参数列表不同。编译器根据参数列表选择符合的函数。
void print(int x) {
std::cout << "Integer: " << x << std::endl;
}
void print(double x) {
std::cout << "Double: " << x << std::endl;
}
int main() {
print(5); // 调用 print(int)
print(5.0); // 调用 print(double)
return 0;
} 5.2 重载规则
[*]参数列表必须不同。
[*]返回范例不同不能作为重载的依据。
[*]参数的常量性和引用性可以作为重载的依据。
5.3 重载示例
void print(const char* str) {
std::cout << "String: " << str << std::endl;
}
void print(const std::string& str) {
std::cout << "String: " << str << std::endl;
}
int main() {
print("Hello"); // 调用 print(const char*)
print(std::string("World")); // 调用 print(const std::string&)
return 0;
} 6. 内联函数
6.1 根本概念
内联函数是一种优化手段,编译器会在调用点直接插入函数体,避免函数调用的开销。
inline int add(int a, int b) {
return a + b;
} 6.2 使用场景
[*]函数体非常短小。
[*]调用频繁。
6.3 内联函数的限定
[*]内联函数的定义必须在所有调用点之前可见。
[*]过多的内联函数大概会增加编译时间和可执行文件的大小。
7. 递归函数
7.1 根本概念
递归函数是指在函数体中调用自身的函数。递归函数需要有一个终止条件,否则会导致无限递归。
int factorial(int n) {
if (n == 0) {
return 1;
}
return n * factorial(n - 1);
}
int main() {
std::cout << "Factorial of 5: " << factorial(5) << std::endl; // 输出 "Factorial of 5: 120"
return 0;
} 7.2 递归优化
尾递归:假如递归调用是函数的末了一个操作,编译器可以优化为循环,避免栈溢出。
int factorial(int n, int result = 1) {
if (n == 0) {
return result;
}
return factorial(n - 1, n * result);
}
int main() {
std::cout << "Factorial of 5: " << factorial(5) << std::endl; // 输出 "Factorial of 5: 120"
return 0;
} 7.3 递归示例:斐波那契数列
int fibonacci(int n) {
if (n <= 1) {
return n;
}
return fibonacci(n - 1) + fibonacci(n - 2);
}
int main() {
std::cout << "Fibonacci of 5: " << fibonacci(5) << std::endl; // 输出 "Fibonacci of 5: 5"
return 0;
} 8. 函数指针
8.1 根本概念
函数指针是指向函数的指针,可以用来调用函数。
int add(int a, int b) {
return a + b;
}int main() { int (*func)(int, int) = add; // 声明并初始化函数指针 int result = func(3, 5); // 调用函数 std::cout << "Result: " << result << std::endl; // 输出 "Result: 8" return 0;} 8.2 函数指针数组
可以使用函数指针数组来存储多个函数指针。
int add(int a, int b) {
return a + b;
}int subtract(int a, int b) { return a - b;}int main() { int (*funcArray)(int, int) = {add, subtract}; // 函数指针数组 int result1 = funcArray(3, 5); // 调用 add int result2 = funcArray(3, 5); // 调用 subtract std::cout << "Result1: " << result1 << ", Result2: " << result2 << std::endl; // 输出 "Result1: 8, Result2: -2" return 0;} 8.3 函数指针作为参数
可以将函数指针作为参数传递给其他函数。
void applyFunction(int (*func)(int, int), int a, int b) {
int result = func(a, b);
std::cout << "Result: " << result << std::endl;
}
int main() {
applyFunction(add, 3, 5); // 输出 "Result: 8"
applyFunction(subtract, 3, 5); // 输出 "Result: -2"
return 0;
} 8.4 函数指针的范例别名
可以使用 typedef 或 using 关键字为函数指针创建范例别名。
typedef int (*FuncPtr)(int, int);
void applyFunction(FuncPtr func, int a, int b) {
int result = func(a, b);
std::cout << "Result: " << result << std::endl;
}
int main() {
applyFunction(add, 3, 5); // 输出 "Result: 8"
applyFunction(subtract, 3, 5); // 输出 "Result: -2"
return 0;
} 9. Lambda 函数
9.1 根本概念
Lambda 函数是一种匿名函数,可以在需要函数的地方直接定义和使用。
int main() {
auto add = [](int a, int b) -> int {
return a + b;
};
int result = add(3, 5);
std::cout << "Result: " << result << std::endl; // 输出 "Result: 8"
return 0;
} 9.2 Lambda 的捕获列表
Lambda 函数可以捕获外部变量,使用捕获列表来指定捕获方式。
int main() {
int x = 10;
auto add = (int a) -> int {
return a + x;
};
int result = add(5);
std::cout << "Result: " << result << std::endl; // 输出 "Result: 15"
return 0;
} 9.3 Lambda 作为参数
Lambda 函数可以作为参数传递给其他函数。
void applyFunction(std::function<int(int, int)> func, int a, int b) {
int result = func(a, b);
std::cout << "Result: " << result << std::endl;
}
int main() {
applyFunction([](int a, int b) -> int { return a + b; }, 3, 5); // 输出 "Result: 8"
applyFunction([](int a, int b) -> int { return a - b; }, 3, 5); // 输出 "Result: -2"
return 0;
} 9.4 Lambda 的捕获方式
[*]按值捕获:,捕获 x 的值。
[*]按引用捕获:[&x],捕获 x 的引用。
[*]捕获所有局部变量:[=],按值捕获所有局部变量。
[*]捕获所有局部变量的引用:[&],按引用捕获所有局部变量。
10. 模板函数
10.1 根本概念
模板函数可以处置惩罚不同范例的参数,提高代码的通用性。
template <typename T>
T add(T a, T b) {
return a + b;
}
int main() {
int result1 = add(3, 5); // 输出 "Result1: 8"
double result2 = add(3.0, 5.0); // 输出 "Result2: 8.0"
std::cout << "Result1: " << result1 << ", Result2: " << result2 << std::endl;
return 0;
} 10.2 模板特化
可以为特定范例提供模板特化,实现特定范例的优化。
template <>
int add<int>(int a, int b) {
return a + b + 1; // 特化版本
}
int main() {
int result1 = add(3, 5); // 输出 "Result1: 9"
double result2 = add(3.0, 5.0); // 输出 "Result2: 8.0"
std::cout << "Result1: " << result1 << ", Result2: " << result2 << std::endl;
return 0;
} 10.3 模板参数
模板参数可以是范例参数,也可以是非范例参数。
template <typename T, int N>
T multiply(T a) {
return a * N;
}
int main() {
int result1 = multiply<int, 5>(3); // 输出 "Result1: 15"
double result2 = multiply<double, 2>(3.0); // 输出 "Result2: 6.0"
std::cout << "Result1: " << result1 << ", Result2: " << result2 << std::endl;
return 0;
} 11. 函数对象
11.1 根本概念
函数对象是指重载了 operator() 的类对象,可以像函数一样调用。
class Add {
public:
int operator()(int a, int b) {
return a + b;
}
};
int main() {
Add add;
int result = add(3, 5);
std::cout << "Result: " << result << std::endl; // 输出 "Result: 8"
return 0;
} 11.2 函数对象的捕获
函数对象可以捕获外部变量,类似于Lambda函数。这可以通过在类中使用成员变量来实现。
class Add {
private:
int base;
public:
Add(int base) : base(base) {}
int operator()(int a) {
return a + base;
}
};
int main() {
Add add(10);
int result = add(5);
std::cout << "Result: " << result << std::endl; // 输出 "Result: 15"
return 0;
} 11.3 函数对象的机动性
函数对象可以提供更多的机动性,例如可以包含多个操作或状态。
class Calculator {
public:
int add(int a, int b) {
return a + b;
}
int subtract(int a, int b) {
return a - b;
}
};
int main() {
Calculator calc;
int result1 = calc.add(3, 5);
int result2 = calc.subtract(3, 5);
std::cout << "Result1: " << result1 << ", Result2: " << result2 << std::endl; // 输出 "Result1: 8, Result2: -2"
return 0;
} 12. 函数的高级用法
12.1 函数模板的默认参数
模板函数可以有默认参数,类似于普通函数。
template <typename T, int N = 2>
T multiply(T a) {
return a * N;
}
int main() {
int result1 = multiply<int>(3); // 使用默认参数 N = 2
int result2 = multiply<int, 5>(3); // 指定参数 N = 5
std::cout << "Result1: " << result1 << ", Result2: " << result2 << std::endl; // 输出 "Result1: 6, Result2: 15"
return 0;
} 12.2 函数模板的显式特化
可以为特定范例提供显式特化,实现特定范例的优化。
template <typename T>T add(T a, T b) { return a + b;}template <>
int add<int>(int a, int b) {
return a + b + 1; // 特化版本
}
int main() {
int result1 = add(3, 5); // 输出 "Result1: 9"
double result2 = add(3.0, 5.0); // 输出 "Result2: 8.0"
std::cout << "Result1: " << result1 << ", Result2: " << result2 << std::endl;
return 0;
} 12.3 函数模板的部分特化
部分特化答应为特定范例的一部分提供特化版本。
template <typename T, typename U>
struct Add {
static T add(T a, U b) {
return a + b;
}
};
template <typename T>
struct Add<T, int> {
static T add(T a, int b) {
return a + b + 1; // 特化版本
}
};
int main() {
int result1 = Add<int, int>::add(3, 5); // 输出 "Result1: 9"
double result2 = Add<double, double>::add(3.0, 5.0); // 输出 "Result2: 8.0"
std::cout << "Result1: " << result1 << ", Result2: " << result2 << std::endl;
return 0;
} 13. 函数的最佳实践
13.1 函数的命名
函数的命名应该清楚、简便,能够反映其功能。使用动词或动词短语来命名函数。
void printMessage(const std::string& message) {
std::cout << message << std::endl;
} 13.2 函数的长度
函数应该保持简短,通常不凌驾20行代码。假如函数过长,可以思量将其拆分为多个函数。
void processRequest(const std::string& request) {
parseRequest(request);
validateRequest(request);
executeRequest(request);
}
void parseRequest(const std::string& request) {
// 解析请求
}
void validateRequest(const std::string& request) {
// 验证请求
}
void executeRequest(const std::string& request) {
// 执行请求
} 13.3 函数的参数
只管减少函数的参数数量。假如参数过多,可以思量使用布局体或类来传递参数。
struct Request {
std::string url;
std::string method;
std::map<std::string, std::string> headers;
};
void processRequest(const Request& request) {
// 处理请求
} 13.4 函数的返回值
函数的返回值应该明确,避免使用全局变量或外部状态来传递结果。
int add(int a, int b) {
return a + b;
} 13.5 函数的错误处置惩罚
函数应该有明确的错误处置惩罚机制,可以使用异常、错误码或可选范例来处置惩罚错误。
int divide(int a, int b) {
if (b == 0) {
throw std::runtime_error("Division by zero");
}
return a / b;
}
int main() {
try {
int result = divide(10, 0);
std::cout << "Result: " << result << std::endl;
} catch (const std::exception& e) {
std::cout << "Error: " << e.what() << std::endl;
}
return 0;
} 14. 应用实例
假设我们需要编写一个简单的计算器步调,该步调可以执行加法、减法、乘法和除法操作。我们将使用前面介绍的函数特性来实现这个步调。
#include <iostream>#include <stdexcept>#include <functional>// 根本运算函数int add(int a, int b) {
return a + b;
}int subtract(int a, int b) { return a - b;}int multiply(int a, int b) { return a * b;}int divide(int a, int b) { if (b == 0) { throw std::runtime_error("Division by zero"); } return a / b;}// 函数指针数组int (*operations)(int, int) = {add, subtract, multiply, divide};// 函数指针范例别名typedef int (*FuncPtr)(int, int);// 执行运算void performOperation(FuncPtr func, int a, int b) { try { int result = func(a, b); std::cout << "Result: " << result << std::endl; } catch (const std::exception& e) { std::cout << "Error: " << e.what() << std::endl; }}// 主函数int main() { int a, b; int choice; std::cout << "Enter two numbers: "; std::cin >> a >> b; std::cout << "Choose an operation:\n"; std::cout << "1. Add\n"; std::cout << "2. Subtract\n"; std::cout << "3. Multiply\n"; std::cout << "4. Divide\n"; std::cin >> choice; if (choice >= 1 && choice <= 4) { performOperation(operations, a, b); } else { std::cout << "Invalid choice" << std::endl; } return 0;} 15. 总结
C++函数是步调计划中的重要组成部分,通过合理地使用函数,可以提高代码的可读性、可维护性和可重用性。本文详细介绍了C++函数的各种特性,包罗函数的定义、调用、参数传递、返回值、重载、内联函数、递归函数、函数指针、Lambda函数、模板函数和函数对象。盼望本文能够资助您更好地理解和使用C++函数。
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
页:
[1]