C++基础 — 函数总结

一、函数核心作用

把一段重复、独立的逻辑封装起来,一次定义、多处调用,实现代码复用、逻辑分层、降低维护成本。

C++函数分为:普通全局函数、类成员函数(构造/析构/普通成员/静态成员/常函数)、内联函数、模板函数、Lambda匿名函数。


二、函数基础语法

1. 完整结构

复制代码
// 返回值类型 函数名(参数列表) { 函数体; return 返回值; }

int add(int a, int b) {

    return a + b;

}
  1. 返回值类型:函数执行完返回的数据类型;无返回写 void

  2. 函数名:标识符,见名知意,不能是关键字

  3. 参数列表:0个/多个,逗号分隔;形参(定义处)、实参(调用处)

  4. 函数体:大括号内执行逻辑

  5. return:终止函数,带回返回值;void函数可省略 return

2. 无参、无返回示例

复制代码
void printHello() {

    std::cout << "Hello C++" << std::endl;

}

 

// 调用

printHello();

3. 有参有返回

复制代码
double mul(double x, double y) {

    return x * y;

}

 

double res = mul(3.14, 2);

三、函数声明 vs 函数定义(对应.h/.cpp)

1. 声明(只告诉编译器函数长什么样,无实现)

放在头文件 .h,作用:提前告知接口,解决"调用在定义前"报错。语法:末尾加分号。

复制代码
// 声明

int add(int a, int b);

2. 定义(完整实现逻辑)

放在 .cpp,只能定义一次。

复制代码
int add(int a, int b) {

    return a + b;

}

工程规范:

.h:放函数声明

.cpp:#include 对应头文件,写函数实现


四、函数参数四大传递方式

1. 值传递(拷贝,最常用)

实参拷贝一份给形参,函数内修改形参不影响外部变量。

复制代码
void test(int x) {

    x = 100;  // 只改副本

}

 

int a = 10;

test(a);  // a 依旧是 10

缺点:大对象(string、类)拷贝开销大。

2. 引用传递 & 常引用(&/const&)

(1)普通引用 T&

形参是实参别名,修改形参直接改外部变量,无拷贝开销。

复制代码
void modify(int& x) {

    x = 999;

}

 

int num = 10;

modify(num);  // num = 999

(2)const 常引用 const T&(最优传参)

只读取、不修改,无拷贝、不能改原数据,传递字符串/类首选。

复制代码
void showStr(const std::string& s) {

    std::cout << s;

    // s = "xxx";  // 报错,const 不可修改

}

3. 指针传递 T*

传递变量地址,通过解引用修改原值,兼容C语言。

复制代码
void setVal(int* p) {

    *p = 666;

}

 

int n = 1;

setVal(&n);

4. 数组参数

数组传参等价于指针,会丢失长度,需额外传大小。

复制代码
void printArr(int arr[], int len) {

    for (int i = 0; i < len; i++)

        std::cout << arr[i];

}

五、默认参数

定义函数时给参数预设值,调用不传则使用默认值。规则:带默认值的参数必须靠右。

复制代码
// 正确:默认参数放后面

void func(int a, int b = 10, double c = 3.14) {}

 

// 调用多种写法

func(1);        // b=10, c=3.14

func(1, 20);    // c=3.14

func(1, 20, 9.9);

 

// 错误:默认参数不能靠左

// void func(int a = 10, int b)  // 编译报错

注意:声明和定义只能一处写默认值,推荐写在 .h 声明里。


六、函数重载 Overload

同一作用域,函数名相同,参数列表不同(个数/类型/顺序),编译器自动匹配对应函数。返回值不能作为重载区分依据。

复制代码
// 重载1

int calc(int a) {

    return a;

}

 

// 重载2

int calc(int a, int b) {

    return a + b;

}

 

// 重载3

double calc(double a) {

    return a * 2;

}

 

calc(10);    // 调用重载1

calc(1, 2);  // 调用重载2

calc(2.5);   // 调用重载3

Qt 中大量使用重载(按钮点击、控件构造)。


七、特殊函数:类内成员函数

1. 构造函数 Constructor

函数名=类名,无返回值,可重载。创建对象自动调用,用于初始化成员变量。

复制代码
class Person {

public:

    Person() {           // 无参构造

        age = 0;

    }

    Person(int a) {      // 有参构造(重载)

        age = a;

    }

private:

    int age;

};

 

Person p1;       // 调用无参构造

Person p2(18);   // 调用有参构造

2. 析构函数 Destructor ~类名()

如:~MainWindow()

波浪号~+类名,无参数、无返回、只能一个。对象销毁时自动调用,释放堆内存、资源、句柄。

复制代码
class MainWindow {

public:

    MainWindow();

    ~MainWindow();  // 析构

};

3. 常成员函数 const

函数末尾加 const,函数内不能修改成员变量,只能读取。

复制代码
class Test {

public:

    int getNum() const {

        // num = 10;  // 报错

        return num;

    }

private:

    int num = 5;

};

4. 静态成员函数 static

属于类,不属于单个对象,只能访问静态成员,没有 this 指针。

复制代码
class Math {

public:

    static int max(int a, int b) {

        return a > b ? a : b;

    }

};

 

// 直接类名调用,不用创建对象

Math::max(3, 9);

八、内联函数 inline

普通函数调用有压栈跳转开销,inline 提示编译器将函数代码直接嵌入调用处,省去调用开销。适用:代码很短(1~5行)、频繁调用的函数。

复制代码
inline int square(int x) {

    return x * x;

}

模板函数默认隐式 inline,必须写在头文件。


九、模板函数 template

通用函数,适配任意数据类型,解决重复写 int/double/string 同款逻辑。

复制代码
template<typename T>

T add(T a, T b) {

    return a + b;

}

 

add<int>(1, 2);          // 返回 3

add<double>(1.1, 2.2);   // 返回 3.3

强制放 .h 头文件,编译器需要完整定义才能实例化。


十、Lambda 匿名函数 C++11+

不用定义函数名,临时写一段逻辑,常用于 Qt 信号槽、排序、遍历。

复制代码
auto func = [](int x) -> int {

    return x * 2;

};

 

std::cout << func(5);  // 输出 10

捕获列表 \[\]:= 值捕获、\& 引用捕获外部变量。


十一、函数递归

函数内部自己调用自己,必须有终止条件,否则死循环栈溢出。

复制代码
// 阶乘

int fact(int n) {

    if (n <= 1) return 1;  // 终止条件

    return n * fact(n - 1);

}

十二、返回值补充

  1. void:无返回,可写 return; 提前退出

  2. 引用返回 int&:可以作为左值修改原变量

  3. 指针返回 int*:返回堆地址,记得外部释放

  4. 函数不能返回局部普通变量的引用/指针(局部变量销毁,悬空引用)


十三、常见易错点

  1. 函数声明加分号,定义不能加分号

  2. 模板、inline 放头文件;普通实现放 .cpp

  3. 重载只看参数,返回值不算区分条件

  4. 默认参数从右往左写

  5. 传大型对象优先 const&,减少拷贝

  6. 析构函数不要手动调用,对象销毁自动执行

相关推荐
leoZ2312 小时前
AI 辅助开发的五道坎
开发语言·人工智能·视觉检测·bert·php·超分辨率重建·openvino
会周易的程序员2 小时前
aiDgePLC — IEC61131-3 ST PLC 虚拟机调试与运行环境
c++·物联网·虚拟机·st·工业协议·iec61131·梯形图
程序员老陆2 小时前
Qt的QThread::usleep和FFmpeg的libavutil模块的av_usleep哪个精度高一些?
开发语言·qt·ffmpeg·音视频
2601_963869952 小时前
【计算机毕业设计】基于Java的相框定制系统的设计与实现
java·开发语言·课程设计
名字还没想好☜3 小时前
Go 的 unsafe.Pointer 实战:零拷贝 []byte↔string 转换与三条铁律
开发语言·后端·golang·go·unsafe
wuminyu4 小时前
JVM利用io_uring优化堆外内存性能原理剖析
java·linux·c语言·jvm·c++
gumichef4 小时前
第二章:C/C++内存管理
c++·内存管理
天天进步20155 小时前
Python全栈项目--协同办公平台
开发语言·python
JAVA面经实录9175 小时前
集合框架 (六)
java·开发语言
xzlAwin5 小时前
Go语言多版本管理器g工具命令
开发语言·golang