【5minC++基本功】C++中的多级指针、泛型指针、与函数指针

【5minC++基本功】C++中的多级指针、范型指针、与函数指针

写在前面

对于指针, 我们一般关注的有以下两点: (1)解指针类型; (2)地址

1. 多级指针

直观来看,多级指针就是一个“解指针的结果仍然为指针”的一种指针. 下面通过代码示例来具体看下:

#include <iostream>

int main() {
    int value = 42;
    int* ptr = &value;      // 单级指针,指向变量 value
    int** ptr2 = &ptr;      // 二级指针,指向指针 ptr
    int*** ptr3 = &ptr2;    // 三级指针,指向指针 ptr2

    std::cout << "Value: " << value << std::endl;               // 输出变量值
    std::cout << "Value via ptr: " << *ptr << std::endl;        // 通过单级指针访问值
    std::cout << "Value via ptr2: " << **ptr2 << std::endl;     // 通过二级指针访问值
    std::cout << "Value via ptr3: " << ***ptr3 << std::endl;    // 通过三级指针访问值

    return 0;
}

输出结果:

Value: 42
Value via ptr: 42
Value via ptr2: 42
Value via ptr3: 42

在这个示例中, ptr 是一个指向 value 的单级指针,ptr2 是一个指向 ptr 的二级指针,而 ptr3 是一个指向 ptr2 的三级指针。通过多级指针,我们可以间接地访问 value 的值。

2. 泛型指针

如果用同样的句式来理解泛型指针,那么它就是“一个解指针类型为空”的指针. 代码示例如下:

#include <iostream>

void printValue(void* ptr, char type) {
    switch (type) {
        case 'i': // int
            std::cout << "Integer value: " << *static_cast<int*>(ptr) << std::endl;
            break;
        case 'f': // float
            std::cout << "Float value: " << *static_cast<float*>(ptr) << std::endl;
            break;
        case 'd': // double
            std::cout << "Double value: " << *static_cast<double*>(ptr) << std::endl;
            break;
        default:
            std::cout << "Unknown type" << std::endl;
    }
}

int main() {
    int i = 42;
    float f = 3.14f;
    double d = 2.718;

    void* ptr;

    ptr = &i;
    printValue(ptr, 'i');

    ptr = &f;
    printValue(ptr, 'f');

    ptr = &d;
    printValue(ptr, 'd');

    return 0;
}

运行结果:

Integer value: 42
Float value: 3.14
Double value: 2.718

在上面的代码中,printValue 函数接收一个 void* 泛型指针和一个字符标识符 type,通过类型转换 (static_cast) 将泛型指针转换为特定类型的指针并输出对应的值。

泛型指针的使用注意
泛型指针 (void*) 则允许指针指向任何类型的数据,提供了一种通用的数据处理方式,但需要在使用时进行显式的类型转换, 例如上面的示例代码中函数printValue, 它在内部先通过static_cast类型转换函数 将泛型指针转换为特定类型的指针,再进行具体的处理。

3. 函数指针

对于函数, 比较关注的有三个要素: (1)首地址; (2)参数; (3)返回值
有一种指针,保存的就是函数的首地址, 用来指向函数、调用函数等, 那就是函数指针。
对一个函数取地址, 其实就是取这个函数首地址的值。

函数指针的定义一般是这种格式: 返回型+函数指针名+入参类型。

return_type (*pointer_name) (parameter_types);

下面看一个具体的例子:

#include <iostream>

// 函数声明
void add(int a, int b);
void subtract(int a, int b);

int main() {
    // 定义函数指针
    void (*funcPtr)(int, int);

    // 将函数指针指向具体的函数
    funcPtr = &add;
    funcPtr(5, 3);  // 调用 add 函数

    funcPtr = &subtract;
    funcPtr(5, 3);  // 调用 subtract 函数

    return 0;
}

// 定义 add 函数
void add(int a, int b) {
    std::cout << "Addition: " << (a + b) << std::endl;
}

// 定义 subtract 函数
void subtract(int a, int b) {
    std::cout << "Subtraction: " << (a - b) << std::endl;
}

以上代码的解释:

  1. 定义函数指针
    在 main 函数中,我们定义了一个函数指针 funcPtr,它可以指向返回类型为 void,参数类型为 int, int 的函数。

  2. 将函数指针指向具体的函数
    通过将 funcPtr 分别指向 add 和 subtract 函数,我们可以使用同一个指针变量调用不同的函数。

  3. 通过指针调用函数
    使用函数指针调用函数的语法与直接调用函数相同。我们通过 funcPtr(5, 3) 调用了 add 和 subtract 函数。

函数指针的使用
函数指针常用于实现回调函数、事件处理器等。
它的一个常见用法是作为参数传递, 这种方式能够帮助我们实现在函数中调用其他函数。很多回调函数都是这样实现的。

#include <iostream>

// 函数声明
void add(int a, int b);
void subtract(int a, int b);
void executeOperation(void (*operation)(int, int), int x, int y);

int main() {
    // 调用 executeOperation 并传递函数指针
    executeOperation(&add, 5, 3);
    executeOperation(&subtract, 5, 3);
    return 0;
}

// 定义 add 函数
void add(int a, int b) {
    std::cout << "Addition: " << (a + b) << std::endl;
}

// 定义 subtract 函数
void subtract(int a, int b) {
    std::cout << "Subtraction: " << (a - b) << std::endl;
}

// 定义 executeOperation 函数
void executeOperation(void (*operation)(int, int), int x, int y) {
    operation(x, y);  // 通过函数指针调用函数
}

以上代码的解释:

  1. 定义 executeOperation 函数
    该函数接受一个函数指针 operation 和两个整数 x、y 作为参数。在函数体内,通过 operation 指针调用传递进来的函数。

  2. 在 main 函数中调用 executeOperation
    我们将 add 和 subtract 函数的地址作为参数传递给 executeOperation,并执行相应的操作。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

steptoward

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值