C++学习之函数提高

简介: C++学习之函数提高

重温C++中的函数概念

在C++中,函数是一段可重用的代码块,用于执行特定的任务。它们是结构化编程和模块化设计的重要组成部分,使得代码更加可读、可维护和可复用。

以下是一些关于C++函数的重要信息:

函数声明和定义

函数需要先进行声明,然后再进行定义。声明告诉编译器函数的名称、返回类型和参数列表等信息。定义提供了函数的具体实现。

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

函数参数

函数可以接受零个或多个参数,用于传递数据给函数。参数可以是基本类型(如整数、浮点数),也可以是自定义类型(如结构体、类)。

// 函数接受两个整数参数,并返回它们的和
int add(int a, int b) {
    return a + b;
}

函数返回值

函数可以返回一个值给调用者。返回值可以是任何有效的数据类型,包括基本类型、自定义类型和指针。

// 函数返回两个整数的和
int add(int a, int b) {
    return a + b;
}
// 函数返回指针类型
int* createArray(int size) {
    int* arrayPtr = new int[size];
    // 初始化数组...
    return arrayPtr;
}

函数重载

C++允许定义多个同名但参数列表不同的函数,这称为函数重载。根据函数调用时提供的参数类型和数量,编译器会选择合适的函数进行调用。

// 两个整数相加
int add(int a, int b) {
    return a + b;
}
// 两个浮点数相加
float add(float a, float b) {
    return a + b;
}

默认参数

C++允许为函数参数提供默认值,这样在调用函数时可以省略对应参数的传递。在函数定义中指定了默认参数后,可以根据需要选择性地提供实际参数值。

// 函数接受两个整数参数,第二个参数有默认值为1
int multiply(int a, int b = 1) {
    return a * b;
}
int result1 = multiply(5, 3);  // 传递两个参数,结果为15
int result2 = multiply(5);     // 只传递一个参数,结果为5

内联函数

使用关键字inline可以定义内联函数。内联函数在每个调用点直接插入函数体的副本,避免了函数调用的开销。但是,内联函数适用于简单且频繁调用的函数,否则可能导致代码膨胀。

inline int add(int a, int b) {
    return a + b;
}

通过函数,可以将代码组织成可重用的模块,提高代码的可读性和可维护性,同时实现更高级的功能。

今天不说其他,就讲:默认参数,占位参数,重载,内联!

C++函数默认参数

当定义函数时,可以为其中的一个或多个参数提供默认值。这些默认参数可以在函数调用时省略,编译器会使用参数的默认值。以下是C++函数默认参数的几种常见用法举例:

单个默认参数

void printMessage(const char* message = "Hello") {
    cout << message << endl;
}
int main() {
    printMessage();         // 输出:Hello
    printMessage("Hi");     // 输出:Hi
    return 0;
}

多个默认参数:

void printInfo(string name, int age, string gender = "Unknown", string occupation = "Unemployed") {
    cout << "Name: " << name << endl;
    cout << "Age: " << age << endl;
    cout << "Gender: " << gender << endl;
    cout << "Occupation: " << occupation << endl;
}
int main() {
    printInfo("John", 25);                 // 输出:John, 25, Unknown, Unemployed
    printInfo("Mary", 30, "Female");        // 输出:Mary, 30, Female, Unemployed
    printInfo("Tom", 35, "Male", "Engineer");   // 输出:Tom, 35, Male, Engineer
    return 0;
}

默认参数可以是常量、变量或者表达式

const int DEFAULT_VALUE = 10;
void multiplyAndPrint(int num1, int num2 = DEFAULT_VALUE * 2) {
    cout << num1 * num2 << endl;
}
int main() {
    multiplyAndPrint(5);       // 输出:50
    multiplyAndPrint(3, 7);    // 输出:21
    return 0;
}

默认参数可以是其他函数调用的结果

int calculateDefaultAge() {
    return 18;
}
void printAge(string name, int age = calculateDefaultAge()) {
    cout << name << ", Age: " << age << endl;
}
int main() {
    printAge("John");     // 输出:John, Age: 18
    printAge("Lucy", 25); // 输出:Lucy, Age: 25
    return 0;
}

注意:C++中有一些限制和规则适用于默认参数的使用:

  • 默认参数必须声明在函数声明或函数原型中,而不是函数定义中。
  • 默认参数一般应该放在参数列表的末尾,从右往左提供默认值。
  • 如果某个函数有多个重载,且其中一个函数提供了默认参数,那么其他重载函数也必须提供默认参数。

正确理解并灵活使用C++函数默认参数,能够简化函数的调用,并提高代码的可读性和可维护性。

C++函数的占位参数

在C++中,占位参数是一种特殊的参数,它没有实际用途,仅作为占位符在函数声明或定义中存在。以下是关于C++函数占位参数的使用讲解和代码示例:

单个占位参数

void printMessage(const char*) {
    cout << "Printing message..." << endl;
}
int main() {
    printMessage("Hello");  // 输出:Printing message...
    return 0;
}

这里的const char*是一个占位参数,它不接收任何参数值。在实际调用函数时,我们不需要提供任何参数值给占位参数。

多个占位参数

void processInput(int, double) {
    cout << "Processing input..." << endl;
}
int main() {
    processInput(10, 3.14);  // 输出:Processing input...
    return 0;
}

这里的intdouble都是占位参数,它们也不接收任何参数值。

在函数模板中使用占位参数

template<typename T>
void displayValue(T) {
    cout << "Displaying value..." << endl;
}
int main() {
    displayValue(5);       // 输出:Displaying value...
    displayValue(3.14);    // 输出:Displaying value...
    return 0;
}

这里的T是一个占位参数,在函数模板中可以接受任何类型的参数值。

函数指针与占位参数

void processInput(int(*)()) {
    cout << "Processing input..." << endl;
}
int getInput() {
    return 10;
}
int main() {
    processInput(getInput);  // 输出:Processing input...
    return 0;
}

这里的int(*)()是一个函数指针类型的占位参数,它表示接受一个无参数并返回int类型的函数指针。

占位参数虽然没有实际用途,但可以在某些情况下起到一些编程技巧上的辅助作用。例如,在设计函数接口时,可能需要保留某个位置用于以后添加功能或拓展。

占位参数并不会对函数的运行时行为产生任何影响。它们只是一个占位符,在函数的声明或定义中使用,无需实际提供参数值。

C++函数的重载

函数重载是C++中一种允许在同一个作用域中定义多个相同名称但参数列表不同的函数的特性。以下是关于C++函数重载的各种用法和代码举例:

参数类型不同

void printValue(int num) {
    cout << "Integer value: " << num << endl;
}
void printValue(double num) {
    cout << "Double value: " << num << endl;
}
int main() {
    printValue(5);       // 输出:Integer value: 5
    printValue(3.14);    // 输出:Double value: 3.14
    return 0;
}

这里有两个名为printValue的函数,一个接受int类型参数,另一个接受double类型参数。根据实际传入的参数类型,编译器会自动调用匹配的函数。

参数个数不同

void calculateSum(int num1, int num2) {
    cout << "Sum: " << num1 + num2 << endl;
}
void calculateSum(int num1, int num2, int num3) {
    cout << "Sum: " << num1 + num2 + num3 << endl;
}
int main() {
    calculateSum(2, 3);          // 输出:Sum: 5
    calculateSum(2, 3, 4);       // 输出:Sum: 9
    return 0;
}

这里有两个名为calculateSum的函数,一个接受两个int类型参数,另一个接受三个int类型参数。编译器根据实际传入的参数个数来选择调用哪一个函数。

参数顺序不同

void printNumbers(int num1, double num2) {
    cout << "Int, Double: " << num1 << ", " << num2 << endl;
}
void printNumbers(double num1, int num2) {
    cout << "Double, Int: " << num1 << ", " << num2 << endl;
}
int main() {
    printNumbers(5, 3.14);       // 输出:Int, Double: 5, 3.14
    printNumbers(3.14, 5);       // 输出:Double, Int: 3.14, 5
    return 0;
}

这里有两个名为printNumbers的函数,一个接受一个int类型参数和一个double类型参数,另一个接受一个double类型参数和一个int类型参数。编译器根据实际传入的参数类型和顺序来选择调用哪一个函数。

函数重载能够提高代码的可读性,并帮助我们使用相同的函数名处理不同的输入情况。在函数重载时,需要注意参数列表的差异,包括参数类型、个数以及顺序等,以确保函数重载能正确匹配到实际调用的函数。

注意哦:和返回值一根毛的关系都没有

C++函数重载的注意事项

在使用C++函数重载时,需要注意以下几个事项:

  1. 参数列表的差异:函数重载的主要依据是参数列表的差异,包括参数类型、个数和顺序等。只有参数列表不同的函数才能进行重载。如果两个函数只有返回类型不同,则不能进行重载。
  2. 二义性问题:当存在多个函数重载时,如果编译器无法确定调用哪个函数,将会产生二义性问题。例如,如果存在两个函数void foo(int)void foo(double),当传入一个整数时,编译器无法确定应该调用哪个函数。这时可以通过强制类型转换或者使用默认参数来解决二义性问题。
  3. 函数匹配规则:编译器在函数重载时会根据一定的匹配规则,选择最合适的函数进行调用。参数完全匹配的函数将得到优先选择。如果没有完全匹配的函数,编译器会尝试进行隐式类型转换,选择最佳匹配的函数。
  4. 返回类型不同不能作为函数重载的依据:函数重载只允许参数列表的差异,返回类型不同不能作为函数重载的依据。因为编译器仅根据函数参数列表来决定选择哪个函数,返回类型并不考虑。
  5. 默认参数的使用:函数重载中,如果一个函数有默认参数,而另一个函数没有,默认参数的函数在实际调用时可能会导致二义性问题。因此,在函数重载中,默认参数的使用需要慎重。
  6. 常量性重载:如果一个函数为常量成员函数(const 成员函数),其重载版本可以包括常量和非常量参数,但不能只有常量参数。这是因为常量成员函数保证不修改对象的状态,因此可以被常量对象调用。

总得来说,使用函数重载时要注意参数列表的差异,并避免出现二义性问题。同时,理解函数匹配规则和返回类型对于函数重载的选择非常重要。在设计函数重载时,应确保函数的行为一致,并尽量简洁明了。

关注我,不迷路,共学习,同进步

关注我,不迷路,共学习,同进步

相关文章
|
24天前
|
编译器 C语言 C++
配置C++的学习环境
【10月更文挑战第18天】如果想要学习C++语言,那就需要配置必要的环境和相关的软件,才可以帮助自己更好的掌握语法知识。 一、本地环境设置 如果您想要设置 C++ 语言环境,您需要确保电脑上有以下两款可用的软件,文本编辑器和 C++ 编译器。 二、文本编辑器 通过编辑器创建的文件通常称为源文件,源文件包含程序源代码。 C++ 程序的源文件通常使用扩展名 .cpp、.cp 或 .c。 在开始编程之前,请确保您有一个文本编辑器,且有足够的经验来编写一个计算机程序,然后把它保存在一个文件中,编译并执行它。 Visual Studio Code:虽然它是一个通用的文本编辑器,但它有很多插
|
29天前
|
程序员 C++ 容器
在 C++中,realloc 函数返回 NULL 时,需要手动释放原来的内存吗?
在 C++ 中,当 realloc 函数返回 NULL 时,表示内存重新分配失败,但原内存块仍然有效,因此需要手动释放原来的内存,以避免内存泄漏。
|
1月前
|
存储 前端开发 C++
C++ 多线程之带返回值的线程处理函数
这篇文章介绍了在C++中使用`async`函数、`packaged_task`和`promise`三种方法来创建带返回值的线程处理函数。
45 6
|
1月前
|
C++
C++ 多线程之线程管理函数
这篇文章介绍了C++中多线程编程的几个关键函数,包括获取线程ID的`get_id()`,延时函数`sleep_for()`,线程让步函数`yield()`,以及阻塞线程直到指定时间的`sleep_until()`。
23 0
C++ 多线程之线程管理函数
|
1月前
|
编译器 C语言 C++
C++入门3——类与对象2-2(类的6个默认成员函数)
C++入门3——类与对象2-2(类的6个默认成员函数)
23 3
|
1月前
|
编译器 C语言 C++
详解C/C++动态内存函数(malloc、free、calloc、realloc)
详解C/C++动态内存函数(malloc、free、calloc、realloc)
158 1
|
1月前
|
存储 编译器 C++
C++入门3——类与对象2-1(类的6个默认成员函数)
C++入门3——类与对象2-1(类的6个默认成员函数)
30 1
|
1月前
|
Java 编译器 C++
c++学习,和友元函数
本文讨论了C++中的友元函数、继承规则、运算符重载以及内存管理的重要性,并提到了指针在C++中的强大功能和使用时需要注意的问题。
21 1
|
1月前
|
编译器 C语言 C++
C++入门6——模板(泛型编程、函数模板、类模板)
C++入门6——模板(泛型编程、函数模板、类模板)
41 0
C++入门6——模板(泛型编程、函数模板、类模板)
|
2月前
|
编译器 C++
【C++核心】函数的应用和提高详解
这篇文章详细讲解了C++函数的定义、调用、值传递、常见样式、声明、分文件编写以及函数提高的内容,包括函数默认参数、占位参数、重载等高级用法。
22 3