Skip to content

C++ 函数及参数传递

概述

函数是C++程序的基本构建块,它将相关的代码组织在一起,实现特定的功能。函数提供了代码重用性、模块化和抽象化的能力。本章将详细介绍函数的定义、调用、参数传递方式以及相关的高级特性。

🔧 函数基础

函数定义和声明

cpp
#include <iostream>

// 函数声明(原型)
int add(int a, int b);
void greet(const std::string& name);
double calculateArea(double radius);

// 函数定义
int add(int a, int b) {
    return a + b;
}

void greet(const std::string& name) {
    std::cout << "Hello, " << name << "!" << std::endl;
}

double calculateArea(double radius) {
    const double PI = 3.14159;
    return PI * radius * radius;
}

int main() {
    // 函数调用
    int result = add(5, 3);
    std::cout << "5 + 3 = " << result << std::endl;
    
    greet("Alice");
    
    double area = calculateArea(5.0);
    std::cout << "半径5的圆面积: " << area << std::endl;
    
    return 0;
}

函数的组成部分

cpp
#include <iostream>

// 函数组成部分详解
/*
返回类型 函数名(参数列表) {
    函数体
    return 返回值;  // 如果返回类型不是void
}
*/

// 1. 无参数函数
void sayHello() {
    std::cout << "Hello, World!" << std::endl;
}

// 2. 有参数函数
int multiply(int x, int y) {
    return x * y;
}

// 3. 默认参数
void printMessage(const std::string& msg, int times = 1) {
    for (int i = 0; i < times; i++) {
        std::cout << msg << std::endl;
    }
}

// 4. 多个返回值(使用结构体)
struct Point {
    double x, y;
};

Point createPoint(double x, double y) {
    return {x, y};  // C++11 列表初始化
}

int main() {
    sayHello();
    
    int product = multiply(4, 7);
    std::cout << "4 × 7 = " << product << std::endl;
    
    printMessage("Default once");
    printMessage("Repeat", 3);
    
    Point p = createPoint(10.5, 20.3);
    std::cout << "Point: (" << p.x << ", " << p.y << ")" << std::endl;
    
    return 0;
}

📦 参数传递方式

值传递(Pass by Value)

cpp
#include <iostream>

// 值传递:传递参数的副本
void modifyValue(int x) {
    x = 100;  // 只修改副本,不影响原变量
    std::cout << "函数内 x = " << x << std::endl;
}

void expensiveCopy(std::vector<int> vec) {
    // 整个vector被复制,开销大
    vec.push_back(999);
    std::cout << "函数内vector大小: " << vec.size() << std::endl;
}

int main() {
    std::cout << "=== 值传递示例 ===" << std::endl;
    
    int original = 42;
    std::cout << "调用前 original = " << original << std::endl;
    
    modifyValue(original);
    std::cout << "调用后 original = " << original << std::endl;  // 仍然是42
    
    std::vector<int> numbers = {1, 2, 3};
    std::cout << "调用前vector大小: " << numbers.size() << std::endl;
    
    expensiveCopy(numbers);
    std::cout << "调用后vector大小: " << numbers.size() << std::endl;  // 仍然是3
    
    return 0;
}

引用传递(Pass by Reference)

cpp
#include <iostream>
#include <vector>

// 引用传递:传递变量的引用(别名)
void modifyByReference(int& x) {
    x = 100;  // 直接修改原变量
    std::cout << "函数内 x = " << x << std::endl;
}

void efficientModify(std::vector<int>& vec) {
    // 不复制vector,直接操作原对象
    vec.push_back(999);
    std::cout << "函数内vector大小: " << vec.size() << std::endl;
}

// const引用:只读访问,不复制
void readOnlyAccess(const std::vector<int>& vec) {
    std::cout << "只读访问,vector大小: " << vec.size() << std::endl;
    // vec.push_back(1);  // 错误!不能修改const引用
}

// 交换两个变量
void swap(int& a, int& b) {
    int temp = a;
    a = b;
    b = temp;
}

int main() {
    std::cout << "=== 引用传递示例 ===" << std::endl;
    
    int original = 42;
    std::cout << "调用前 original = " << original << std::endl;
    
    modifyByReference(original);
    std::cout << "调用后 original = " << original << std::endl;  // 变成100
    
    std::vector<int> numbers = {1, 2, 3};
    std::cout << "调用前vector大小: " << numbers.size() << std::endl;
    
    efficientModify(numbers);
    std::cout << "调用后vector大小: " << numbers.size() << std::endl;  // 变成4
    
    readOnlyAccess(numbers);
    
    // 交换示例
    int x = 10, y = 20;
    std::cout << "交换前: x = " << x << ", y = " << y << std::endl;
    swap(x, y);
    std::cout << "交换后: x = " << x << ", y = " << y << std::endl;
    
    return 0;
}

指针传递(Pass by Pointer)

cpp
#include <iostream>

// 指针传递:传递变量地址的副本
void modifyByPointer(int* x) {
    if (x != nullptr) {  // 安全检查
        *x = 100;  // 通过指针修改原变量
        std::cout << "函数内 *x = " << *x << std::endl;
    }
}

void allocateMemory(int** ptr, int size) {
    *ptr = new int[size];  // 修改指针本身
    for (int i = 0; i < size; i++) {
        (*ptr)[i] = i + 1;
    }
}

// 比较字符串长度
int compareStringLength(const char* str1, const char* str2) {
    int len1 = strlen(str1);
    int len2 = strlen(str2);
    return len1 - len2;
}

int main() {
    std::cout << "=== 指针传递示例 ===" << std::endl;
    
    int original = 42;
    std::cout << "调用前 original = " << original << std::endl;
    
    modifyByPointer(&original);  // 传递地址
    std::cout << "调用后 original = " << original << std::endl;
    
    // 空指针安全
    modifyByPointer(nullptr);  // 不会崩溃
    
    // 动态内存分配
    int* array = nullptr;
    allocateMemory(&array, 5);
    
    std::cout << "动态分配的数组: ";
    for (int i = 0; i < 5; i++) {
        std::cout << array[i] << " ";
    }
    std::cout << std::endl;
    
    delete[] array;  // 释放内存
    
    // 字符串比较
    const char* str1 = "hello";
    const char* str2 = "world";
    int diff = compareStringLength(str1, str2);
    std::cout << "字符串长度差: " << diff << std::endl;
    
    return 0;
}

🎯 函数重载

基本函数重载

cpp
#include <iostream>
#include <string>

// 函数重载:相同函数名,不同参数
class Calculator {
public:
    // 整数加法
    int add(int a, int b) {
        std::cout << "整数加法: ";
        return a + b;
    }
    
    // 浮点数加法
    double add(double a, double b) {
        std::cout << "浮点数加法: ";
        return a + b;
    }
    
    // 三个参数的加法
    int add(int a, int b, int c) {
        std::cout << "三数加法: ";
        return a + b + c;
    }
    
    // 字符串连接
    std::string add(const std::string& a, const std::string& b) {
        std::cout << "字符串连接: ";
        return a + b;
    }
};

// 全局函数重载
void print(int value) {
    std::cout << "整数: " << value << std::endl;
}

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

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

void print(const char* value) {
    std::cout << "C字符串: " << value << std::endl;
}

int main() {
    Calculator calc;
    
    std::cout << calc.add(5, 3) << std::endl;
    std::cout << calc.add(2.5, 3.7) << std::endl;
    std::cout << calc.add(1, 2, 3) << std::endl;
    std::cout << calc.add(std::string("Hello, "), std::string("World!")) << std::endl;
    
    // 函数重载解析
    print(42);
    print(3.14);
    print(std::string("C++ String"));
    print("C String");
    
    return 0;
}

重载解析规则

cpp
#include <iostream>

// 重载解析优先级演示
void func(int x) {
    std::cout << "func(int): " << x << std::endl;
}

void func(double x) {
    std::cout << "func(double): " << x << std::endl;
}

void func(int x, int y) {
    std::cout << "func(int, int): " << x << ", " << y << std::endl;
}

// const重载
void process(int& x) {
    std::cout << "process(int&): " << x << std::endl;
    x++;
}

void process(const int& x) {
    std::cout << "process(const int&): " << x << std::endl;
}

int main() {
    std::cout << "=== 重载解析示例 ===" << std::endl;
    
    // 精确匹配
    func(42);        // 调用 func(int)
    func(3.14);      // 调用 func(double)
    func(1, 2);      // 调用 func(int, int)
    
    // 类型转换
    func(3.14f);     // float->double, 调用 func(double)
    
    // const重载
    int mutable_var = 10;
    const int const_var = 20;
    
    process(mutable_var);    // 调用 process(int&)
    process(const_var);      // 调用 process(const int&)
    process(100);            // 临时对象,调用 process(const int&)
    
    return 0;
}

📚 高级函数特性

默认参数

cpp
#include <iostream>
#include <string>

// 默认参数函数
void createUser(const std::string& name, 
                int age = 0, 
                const std::string& email = "unknown@example.com",
                bool isActive = true) {
    std::cout << "用户信息:" << std::endl;
    std::cout << "  姓名: " << name << std::endl;
    std::cout << "  年龄: " << age << std::endl;
    std::cout << "  邮箱: " << email << std::endl;
    std::cout << "  状态: " << (isActive ? "活跃" : "非活跃") << std::endl;
    std::cout << std::endl;
}

// 默认参数规则
void configureSettings(int width = 800, int height = 600, bool fullscreen = false);

// 实现必须省略默认值
void configureSettings(int width, int height, bool fullscreen) {
    std::cout << "设置: " << width << "x" << height 
              << (fullscreen ? " (全屏)" : " (窗口)") << std::endl;
}

int main() {
    std::cout << "=== 默认参数示例 ===" << std::endl;
    
    // 不同的调用方式
    createUser("Alice");                                    // 只传必需参数
    createUser("Bob", 25);                                 // 传递部分参数
    createUser("Charlie", 30, "charlie@email.com");        // 传递更多参数
    createUser("Diana", 28, "diana@email.com", false);     // 传递所有参数
    
    // 配置示例
    configureSettings();                    // 使用所有默认值
    configureSettings(1024);                // 只设置宽度
    configureSettings(1920, 1080);          // 设置宽度和高度
    configureSettings(1920, 1080, true);    // 设置所有参数
    
    return 0;
}

内联函数

cpp
#include <iostream>

// 内联函数:建议编译器在调用处展开
inline int max(int a, int b) {
    return (a > b) ? a : b;
}

inline double square(double x) {
    return x * x;
}

// 类内定义的函数自动成为内联函数
class MathUtils {
public:
    // 自动内联
    int add(int a, int b) {
        return a + b;
    }
    
    // 显式内联
    inline double multiply(double a, double b) {
        return a * b;
    }
};

// 复杂函数不适合内联
inline void complexFunction() {
    // 包含循环、递归等复杂逻辑的函数
    // 编译器可能忽略内联建议
    for (int i = 0; i < 1000; i++) {
        std::cout << "This is too complex for inlining" << std::endl;
    }
}

int main() {
    std::cout << "=== 内联函数示例 ===" << std::endl;
    
    int result = max(10, 20);
    std::cout << "max(10, 20) = " << result << std::endl;
    
    double sq = square(5.5);
    std::cout << "square(5.5) = " << sq << std::endl;
    
    MathUtils utils;
    std::cout << "add(3, 4) = " << utils.add(3, 4) << std::endl;
    std::cout << "multiply(2.5, 4.0) = " << utils.multiply(2.5, 4.0) << std::endl;
    
    return 0;
}

函数指针和函数对象

cpp
#include <iostream>
#include <functional>

// 普通函数
int add(int a, int b) {
    return a + b;
}

int multiply(int a, int b) {
    return a * b;
}

// 函数对象(仿函数)
class Subtract {
public:
    int operator()(int a, int b) const {
        return a - b;
    }
};

// 使用函数指针的高阶函数
int calculate(int x, int y, int (*operation)(int, int)) {
    return operation(x, y);
}

// 使用std::function的高阶函数
int flexibleCalculate(int x, int y, const std::function<int(int, int)>& operation) {
    return operation(x, y);
}

int main() {
    std::cout << "=== 函数指针和函数对象 ===" << std::endl;
    
    // 函数指针
    int (*funcPtr)(int, int) = add;
    std::cout << "函数指针调用: " << funcPtr(5, 3) << std::endl;
    
    // 函数指针数组
    int (*operations[])(int, int) = {add, multiply};
    std::cout << "add(10, 5) = " << operations[0](10, 5) << std::endl;
    std::cout << "multiply(10, 5) = " << operations[1](10, 5) << std::endl;
    
    // 高阶函数
    std::cout << "calculate with add: " << calculate(8, 3, add) << std::endl;
    std::cout << "calculate with multiply: " << calculate(8, 3, multiply) << std::endl;
    
    // 函数对象
    Subtract sub;
    std::cout << "函数对象: " << sub(10, 4) << std::endl;
    
    // std::function
    std::function<int(int, int)> func = add;
    std::cout << "std::function: " << flexibleCalculate(7, 2, func) << std::endl;
    
    func = multiply;
    std::cout << "std::function: " << flexibleCalculate(7, 2, func) << std::endl;
    
    func = sub;
    std::cout << "std::function: " << flexibleCalculate(7, 2, func) << std::endl;
    
    // Lambda表达式
    auto lambda = [](int a, int b) { return a / b; };
    std::cout << "Lambda: " << flexibleCalculate(15, 3, lambda) << std::endl;
    
    return 0;
}

🔄 递归函数

基本递归

cpp
#include <iostream>

// 阶乘计算
unsigned long long factorial(int n) {
    // 基础情况
    if (n <= 1) {
        return 1;
    }
    // 递归调用
    return n * factorial(n - 1);
}

// 斐波那契数列
int fibonacci(int n) {
    if (n <= 1) {
        return n;
    }
    return fibonacci(n - 1) + fibonacci(n - 2);
}

// 优化的斐波那契(记忆化)
int fibonacciOptimized(int n, int memo[] = nullptr) {
    static int staticMemo[100] = {0};
    if (memo == nullptr) memo = staticMemo;
    
    if (n <= 1) return n;
    if (memo[n] != 0) return memo[n];
    
    memo[n] = fibonacciOptimized(n - 1, memo) + fibonacciOptimized(n - 2, memo);
    return memo[n];
}

// 二分查找(递归版本)
bool binarySearch(const int arr[], int left, int right, int target) {
    if (left > right) {
        return false;  // 未找到
    }
    
    int mid = left + (right - left) / 2;
    
    if (arr[mid] == target) {
        return true;   // 找到了
    } else if (arr[mid] > target) {
        return binarySearch(arr, left, mid - 1, target);
    } else {
        return binarySearch(arr, mid + 1, right, target);
    }
}

int main() {
    std::cout << "=== 递归函数示例 ===" << std::endl;
    
    // 阶乘
    for (int i = 0; i <= 10; i++) {
        std::cout << i << "! = " << factorial(i) << std::endl;
    }
    
    // 斐波那契
    std::cout << "\n斐波那契数列:" << std::endl;
    for (int i = 0; i <= 10; i++) {
        std::cout << "F(" << i << ") = " << fibonacci(i) << std::endl;
    }
    
    // 优化的斐波那契
    std::cout << "\n优化的斐波那契:" << std::endl;
    std::cout << "F(30) = " << fibonacciOptimized(30) << std::endl;
    
    // 二分查找
    int sortedArray[] = {1, 3, 5, 7, 9, 11, 13, 15, 17, 19};
    int size = sizeof(sortedArray) / sizeof(sortedArray[0]);
    
    int target = 7;
    bool found = binarySearch(sortedArray, 0, size - 1, target);
    std::cout << "\n查找 " << target << ": " << (found ? "找到" : "未找到") << std::endl;
    
    target = 8;
    found = binarySearch(sortedArray, 0, size - 1, target);
    std::cout << "查找 " << target << ": " << (found ? "找到" : "未找到") << std::endl;
    
    return 0;
}

📋 函数最佳实践

函数设计原则

cpp
#include <iostream>
#include <vector>
#include <string>

// 1. 单一职责原则
bool isValidEmail(const std::string& email) {
    // 简化的邮箱验证
    return email.find('@') != std::string::npos && 
           email.find('.') != std::string::npos;
}

void sendEmail(const std::string& to, const std::string& subject, const std::string& body) {
    if (!isValidEmail(to)) {
        std::cout << "无效的邮箱地址: " << to << std::endl;
        return;
    }
    
    // 发送邮件的逻辑
    std::cout << "发送邮件到: " << to << std::endl;
    std::cout << "主题: " << subject << std::endl;
    std::cout << "内容: " << body << std::endl;
}

// 2. 输入验证
double safeDivide(double numerator, double denominator) {
    if (denominator == 0.0) {
        std::cerr << "错误:除数不能为零" << std::endl;
        return 0.0;  // 或抛出异常
    }
    return numerator / denominator;
}

// 3. 使用const正确性
void printVector(const std::vector<int>& vec) {  // const引用,不修改不复制
    for (const int& value : vec) {
        std::cout << value << " ";
    }
    std::cout << std::endl;
}

// 4. 明确的函数命名
bool isEmpty(const std::string& str) {
    return str.empty();
}

int getLength(const std::string& str) {
    return str.length();
}

void updateUserStatus(int userId, bool isActive) {
    std::cout << "更新用户 " << userId << " 状态为: " 
              << (isActive ? "活跃" : "非活跃") << std::endl;
}

int main() {
    std::cout << "=== 函数设计最佳实践 ===" << std::endl;
    
    // 使用验证函数
    sendEmail("user@example.com", "测试", "这是一封测试邮件");
    sendEmail("invalid-email", "测试", "这不会发送");
    
    // 安全除法
    std::cout << "10 / 2 = " << safeDivide(10.0, 2.0) << std::endl;
    std::cout << "10 / 0 = " << safeDivide(10.0, 0.0) << std::endl;
    
    // const正确性
    std::vector<int> numbers = {1, 2, 3, 4, 5};
    printVector(numbers);
    
    // 明确的函数使用
    std::string text = "Hello";
    std::cout << "字符串是否为空: " << isEmpty(text) << std::endl;
    std::cout << "字符串长度: " << getLength(text) << std::endl;
    
    updateUserStatus(123, true);
    
    return 0;
}

总结

C++函数是构建程序的重要工具,提供了代码组织和重用的能力:

核心概念

  • 函数定义:返回类型、函数名、参数列表、函数体
  • 参数传递:值传递、引用传递、指针传递
  • 函数重载:相同函数名,不同参数类型或数量
  • 高级特性:默认参数、内联函数、递归、函数指针

最佳实践

  • 使用const引用传递大对象避免复制
  • 合理使用函数重载提高接口易用性
  • 遵循单一职责原则设计函数
  • 进行输入验证保证函数健壮性
  • 使用清晰的函数命名表达意图

掌握函数的使用是C++编程的基础,良好的函数设计能显著提高代码的可读性、可维护性和重用性。

本站内容仅供学习和研究使用。