函数璀璨之路:探索C++函数的进阶之道

简介: 函数璀璨之路:探索C++函数的进阶之道

1. 内联函数

内联函数是C++中一种特殊的函数,它的特点是在函数调用的地方将函数体直接嵌入,而不进行函数的调用过程。这样可以减少函数调用的开销,提高程序的运行效率。


【例1-1】使用内联函数


下面是一个使用内联函数的实际案例:

#include <iostream>
// 内联函数的声明和定义写在同一个文件中
// 内联函数的定义需要加上inline关键字
inline int square(int num) 
{
    return num * num;
}
int main() 
{
    int num;
    std::cout << "请输入一个整数:";
    std::cin >> num;
    // 使用内联函数计算平方
    int result = square(num);
    std::cout << num << "的平方是:" << result << std::endl;
    return 0;
}

代码分析:


1.首先,我们包含了iostream头文件,以便能够使用输入输出流。这是C++中处理输入输出的标准库。

2.然后,我们定义了一个内联函数square,该函数接受一个整数参数num,并返回num的平方。

3。在main函数中,我们首先声明了一个整数变量num,用于存储用户输入的数值。

4.接下来,我们通过输入流std::cin输入一个整数,并将其保存到num变量中。

5.然后,我们调用内联函数square,将num作为参数传入,计算得到结果,并将结果保存到result变量中。

6.最后,我们通过输出流std::cout输出计算结果。

通过这个例子,我们可以看到使用内联函数可以简化代码结构,并且能够提高程序的运行效率。但需要注意的是,内联函数适用于函数体代码比较短小的情况,因为将函数体嵌入调用处会增加代码量,如果函数体较长,反而会降低程序的效率。


2. 函数重载

函数重载是指在同一个作用域内,可以有多个同名函数,但它们的参数列表必须不同,包括参数个数、参数类型或参数顺序。函数重载的目的是为了对不同类型的数据进行相似的操作,但具体的处理方式可能不同。


【例1-2】使用重载函数


示例代码如下:


#include <iostream>
using namespace std;
// 函数重载示例1:计算两个整数的和
int add(int x, int y)
{
    return x + y;
}
// 函数重载示例2:计算两个浮点数的和
float add(float x, float y)
{
    return x + y;
}
// 函数重载示例3:计算两个字符串的拼接结果
string add(string x, string y)
{
    return x + y;
}
int main()
{
    int num1 = 5, num2 = 10;
    float f1 = 3.14, f2 = 4.5;
    string str1 = "Hello", str2 = "World";
    cout << "整数相加结果:" << add(num1, num2) << endl;
    cout << "浮点数相加结果:" << add(f1, f2) << endl;
    cout << "字符串相加结果:" << add(str1, str2) << endl;
    return 0;
}

代码分析:


在例1-2中,我们定义了三个同名的函数 add,它们分别用于计算两个整数的和、两个浮点数的和以及两个字符串的拼接结果。


在 main 函数中,我们分别定义了两个整型变量 num1 和 num2,浮点型变量 f1 和 f2,以及字符串变量 str1 和 str2。


然后,我们使用 cout 输出调用不同重载函数的结果。可以看到,不同类型的参数调用了对应的重载函数,实现了相似的操作,但具体的处理方式不同。


运行结果如下:

整数相加结果:15
浮点数相加结果:7.64
字符串相加结果:HelloWorld

总结:


函数重载可以通过不同的参数列表实现相似操作的功能,增加代码的灵活性和可读性。在使用函数重载时,要注意参数列表的不同,确保能够正确匹配到对应的重载函数。

C++学习笔记: 默认参数值


3. 默认参数值

在C++中,函数可以拥有默认参数值。使用默认参数值可以使函数调用更为便捷,同时也提供了更大的灵活性。


3.1 带默认参数值的函数

定义一个带有默认参数值的函数会使得函数在某些情况下可以省略参数的值。当调用函数时,如果没有显式提供相应参数的值,则会使用默认参数。


【例1-3】使用带默认参数值的函数求 x 的 n 次方(n 是正整数)

#include<iostream>
using namespace std;
// 带有默认参数值的函数
int power(int x, int n = 2)
{
    int result = 1;
    for(int i = 0; i < n; i++)
    {
        result *= x;
    }
    return result;
}
int main()
{
    int x = 5;
    int n = 3;    
    // 使用默认参数值
    int result1 = power(x);
    cout << "默认参数值结果:" << result1 << endl;    
    // 不使用默认参数值
    int result2 = power(x, n);
    cout << "指定参数值结果:" << result2 << endl;    
    return 0;
}

输出结果:

默认参数值结果:25
指定参数值结果:125

在上面的例子中,函数power具有默认参数值n = 2。当调用power(x)时,计算的是x的平方。当调用power(x, n)时,计算的是x的n次方。


3.2 默认参数值产生的二义性

当存在多个带有默认参数值的函数时,调用时可能会发生二义性,编译器无法确定调用哪个函数。


【例1-4】重载函数使用默认参数值产生的二义性

#include<iostream>
using namespace std;
// 带有默认参数值的函数
void print(int x, int y = 10)
{
    cout << "x = " << x << ", y = " << y << endl;
}
// 带有默认参数值的函数的重载版本
void print(int x)
{
    cout << "x = " << x << endl;
}
int main()
{
    int x = 5;
    int y = 15;    
    // 发生二义性,无法确定调用哪个函数
    print(x); 
    return 0;
}

运行结果:

编译错误:对 `print` 函数的调用是二义性的

在上面的例子中,存在两个重载的函数print,它们具有不同数量的参数,并且其中一个参数拥有默认值。当调用print(x)时,编译器无法确定是调用哪个函数,因为第一个函数可以省略第二个参数。这时,会产生二义性,从而导致编译错误。


在编写程序时,如果使用了带有默认参数值的函数,请确保没有产生二义性,以免造成编译错误。


4. 函数指针简介

函数指针是指向函数的指针变量。通过函数指针,可以动态地调用不同的函数,实现灵活的函数调用。函数指针的类型必须与目标函数的参数列表和返回值类型一致。


【例1-5】使用函数指针调用函数

#include <iostream>
using namespace std; 
// 定义两个相加的函数
int add(int a, int b) 
{
  return a + b;
}
int main() 
{
  // 声明一个函数指针
  int (*funcPtr)(int, int);
  // 将函数指针指向add函数
  funcPtr = &add;
  // 使用函数指针调用add函数
  int result = (*funcPtr)(3, 4);
  cout << "结果为:" << result << endl;
  return 0;
}

代码分析:


首先,在全局作用域下定义了一个函数add,用于计算两个整数的和。

在主函数中,声明了一个函数指针funcPtr,它可以指向接受两个int类型参数并返回int类型的函数。

将funcPtr指向add函数,可以直接使用函数指针调用add函数,得到结果并输出。

【例1-6】函数指针的应用

#include <iostream>
using namespace std;
// 定义一个排序函数,将数组按照升序排列
void bubbleSort(int arr[], int size) 
{
  for (int i = 0; i < size - 1; i++) 
  {
    for (int j = 0; j < size - i - 1; j++) 
    {
      if (arr[j] > arr[j + 1]) 
      {
        // 交换元素
        int temp = arr[j];
        arr[j] = arr[j + 1];
        arr[j + 1] = temp;
      }
    }
  }
}
// 定义一个函数,接受一个排序函数的指针,并调用该排序函数对数组进行排序
void sortArray(int arr[], int size, void (*sortFunc)(int[], int)) 
{
  // 调用排序函数
  (*sortFunc)(arr, size);
}
int main() 
{
  int arr[] = {5, 1, 3, 2, 4};
  int size = sizeof(arr) / sizeof(arr[0]);
  // 调用sortArray函数并传入bubbleSort函数的指针
  sortArray(arr, size, &bubbleSort);
  // 输出排序后的结果
  for (int i = 0; i < size; i++) 
  {
    cout << arr[i] << " ";
  }
  cout << endl;
  return 0;
}

代码分析:


上述代码中,首先定义了一个冒泡排序函数bubbleSort,用于对传入的数组按照升序进行排序。

然后,定义了一个sortArray函数,接受一个排序函数的指针作为参数,并调用该排序函数对数组进行排序。

在主函数中,创建一个整数数组并初始化,然后调用sortArray函数,并将bubbleSort函数的指针作为参数传递给sortArray函数,实现对数组的排序。

最后,输出排序后的结果。

C++学习笔记:命令行参数

5 命令行参数

5.1 命令行参数

命令行参数是指在程序运行时通过命令行输入的一些参数,可以用来影响程序的行为和输出结果。在C++中,我们可以使用main函数来接收命令行参数。

int main(int argc, char* argv[])
{
    // argc表示命令行参数的个数,包括程序本身
    // argv是一个指针数组,每个元素指向一个命令行参数的字符串    
    // 使用命令行参数进行计算
    if(argc < 4) // 确保输入了足够的参数
    {
        std::cout << "Usage: calculator <operator> <operand1> <operand2>" << std::endl;
        return 1;
    }    
    char op = argv[1][0]; // 第一个参数是操作符
    double operand1 = std::stod(argv[2]); // 第二个参数是第一个操作数
    double operand2 = std::stod(argv[3]); // 第三个参数是第二个操作数    
    // 进行相应的计算
    double result;
    switch(op)
    {
        case '+':
            result = operand1 + operand2;
            break;
        case '-':
            result = operand1 - operand2;
            break;
        case '*':
            result = operand1 * operand2;
            break;
        case '/':
            result = operand1 / operand2;
            break;
        default:
            std::cout << "Invalid operator" << std::endl;
            return 1;
    }    
    std::cout << "Result: " << result << std::endl;
    return 0;
}

上面的例子是一个简单的加减乘除计算器,通过命令行参数指定运算符和操作数,然后输出结果。


5.2 带有命令行参数的程序的运行

要在命令行中运行带有命令行参数的C++程序,可以使用以下格式:

program_name argument1 argument2 ...

其中,program_name 是要运行的程序名称,argument1、argument2 等是传递给程序的参数。这些参数之间用空格分隔。


例如,在命令行中输入以下命令:

calculator + 4 5

程序输出:

Result: 9

这是因为我们指定了加法运算符和两个操作数4和5,计算结果为9。

C++学习笔记:变量的存储类别


6. 变量的存储类别

6.1 内部变量与外部变量

在C++中,变量的存储类别分为内部变量和外部变量。内部变量在函数或代码块内声明并定义,其作用范围仅限于当前函数或代码块。外部变量在函数外部声明并定义,其作用范围可以跨越多个函数或代码块。


【例1-8】使用局部变量和全局变量

#include <iostream>
using namespace std;
int global_var = 10; // 全局变量
void testFunction() 
{
   int local_var = 20; // 局部变量
   cout << "全局变量: " << global_var << endl;
   cout << "局部变量: " << local_var << endl;
}
int main() 
{
   testFunction();
   return 0;
}

在这个例子中,我们定义了一个全局变量global_var和一个局部变量local_var。在testFunction函数中,我们分别输出了这两个变量的值。运行程序后,输出结果为:

全局变量: 10
局部变量: 20

可以看到,全局变量的作用范围跨越了testFunction函数,并且可以被函数内部访问。而局部变量的作用范围仅限于testFunction函数内部。


6.2 变量的存储类别

变量的存储类别除了内部变量和外部变量之外,还可以分为静态变量和自动变量。静态变量在程序执行期间一直存在,不受函数调用的影响。自动变量在函数调用时创建,在函数调用结束后销毁。


【例1-9】输出1~4的阶乘

#include <iostream> 
using namespace std;
int factorial(int n) 
{
   static int result = 1; // 静态变量
   result *= n;
   return result;
}
int main() 
{
   for (int i = 1; i <= 4; i++) 
   {
      cout << i << "的阶乘: " << factorial(i) << endl;
   }
   return 0;
}

在这个例子中,我们定义了一个全局函数factorial,该函数接受一个整数参数n,并计算n的阶乘。我们使用了一个静态变量result来保存计算结果,并且在每次调用函数时更新result的值。在main函数中,我们使用一个循环来计算1到4的阶乘,并输出结果。运行程序后,输出结果为:

1的阶乘: 1
2的阶乘: 2
3的阶乘: 6
4的阶乘: 24

可以看到,静态变量result在多次函数调用之间保持了其值的持久性。


【例1-10】静态变量与自动变量的使用


#include <iostream>
using namespace std;
void testFunction() 
{
   static int static_var = 0; // 静态变量
   int auto_var = 0;          // 自动变量
   static_var++;
   auto_var++;
   cout << "静态变量: " << static_var << endl;
   cout << "自动变量: " << auto_var << endl;
}
int main() 
{
   for (int i = 1; i <= 3; i++) 
   {
      cout << "第" << i << "次函数调用:" << endl;
      testFunction();
      cout << endl;
   }
   return 0;
}

在这个例子中,我们定义了一个函数testFunction,该函数内部分别定义了一个静态变量static_var和一个自动变量auto_var。在每次函数调用时,我们分别对这两个变量进行自增操作,并输出它们的值。在main函数中,我们使用一个循环来调用testFunction函数多次,并输出结果。运行程序后,输出结果为:

第1次函数调用:
静态变量: 1
自动变量: 1
第2次函数调用:
静态变量: 2
自动变量: 1
第3次函数调用:
静态变量: 3
自动变量: 1

可以看到,静态变量static_var在多次函数调用之间保持了其值的持久性,而自动变量auto_var在每次函数调用时都重新初始化。


相关文章
|
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)
161 1
|
1月前
|
存储 编译器 C++
C++入门3——类与对象2-1(类的6个默认成员函数)
C++入门3——类与对象2-1(类的6个默认成员函数)
31 1
|
1月前
|
编译器 C语言 C++
C++入门6——模板(泛型编程、函数模板、类模板)
C++入门6——模板(泛型编程、函数模板、类模板)
41 0
C++入门6——模板(泛型编程、函数模板、类模板)
|
2月前
|
编译器 C++
【C++核心】函数的应用和提高详解
这篇文章详细讲解了C++函数的定义、调用、值传递、常见样式、声明、分文件编写以及函数提高的内容,包括函数默认参数、占位参数、重载等高级用法。
22 3
|
3月前
|
编译器 C++ 容器
【C++】String常见函数用法
【C++】String常见函数用法
|
3月前
|
C++
c++常见函数及技巧
C++编程中的一些常见函数和技巧,包括生成随机数的方法、制表技巧、获取数字的个位、十位、百位数的方法、字符串命名技巧、避免代码修改错误的技巧、暂停和等待用户信号的技巧、清屏命令、以及避免编译错误和逻辑错误的建议。
35 6