服务器之家:专注于VPS、云服务器配置技术及软件下载分享
分类导航

PHP教程|ASP.NET教程|Java教程|ASP教程|编程技术|正则表达式|C/C++|IOS|C#|Swift|Android|VB|R语言|JavaScript|易语言|vb.net|

服务器之家 - 编程语言 - C/C++ - C++函数指针+对象指针+this指针+指向类静态和非静态成员的指针

C++函数指针+对象指针+this指针+指向类静态和非静态成员的指针

2022-10-14 13:36机器学习入坑者 C/C++

这篇文章主要介绍了C++函数指针+对象指针+this指针+指向类静态和非静态成员的指针,函数指针定义和赋值的语法指其中数据类型代表指向函数的返回类型,形参表为指向函数的形参表,更多相关资料需要的朋友可以参考一下下面文

C++函数指针+对象指针+this指针+指向类静态和非静态成员的指针

1、指向函数的指针

函数的代码在内存中的首地址,是由函数名表示的,也就是说函数名等价于函数代码首地址。因此,可以定义一个指向函数的指针,即函数指针。函数指针定义和赋值的语法如下,其中数据类型代表指向函数的返回类型,形参表为指向函数的形参表;赋值时必须保证指向的函数名和函数指针的返回类型和形参完全相同:

数据类型 (*函数指针名)(形参表);
函数指针名 = 函数名;

下面的例子定义了一个函数和一个函数指针,通过函数指针调用函数代码:

?
1
2
3
4
5
6
7
8
9
10
11
12
/// 1、预先定义一个返回int类型的函数
int addOne(int x) {
    x = x + 1;
    return x;
}
 
/// 2、定义并赋值函数指针
int (*pointerAddOne)(int x);
pointerAddOne = addOne;
 
/// 3、使用函数指针和使用函数名的方式相同
data = pointerAddOne(data);

2、对象指针

顾名思义,对象指针表示指向对象的指针。对象名即对象的地址,所以可以将对象的地址赋值给同类型的指针,从而通过该指针使用此对象。

定义与使用对象指针包含4个步骤:

  • 定义XXX类型指针;
  • 定义XXX类型对象;
  • 将对象地址赋值给指针;
  • 使用“(*对象指针名).成员名”或者“对象指针名->成员名”的形式使用对象的成员;

下面的例子展示了对象指针的定义与使用:

?
1
2
3
4
5
6
7
Duck duck(666);
/// 定义并赋值对象指针
Duck *pointerDuck;
pointerDuck = &duck;
/// 对象指针采用两种方式访问对象的成员
printf("%d \n", (*pointerDuck).getAge());
printf("%d \n", pointerDuck->getAge());

3、this指针

C++中,类的每个对象的数据成员都需要单独分配内存,但是类的所有对象的函数成员共享内存。this指针是对象的非静态成员函数的隐含参数,不需要自己进行定义,this指针指向当前调用非静态成员函数的对象。当类对象调用非静态成员函数时,对象的地址作为this指针的值,进而非静态成员函数通过this指向的地址,来访问对象的数据成员(类的不同对象的数据成员存储在不同的地址,this指针用于传递对象的地址)。

this指针访问其指向的对象数据成员的语法为:

this->数据成员名

下面的例子中,Duck类的成员函数getAge需要访问对象的数据成员duckAge,但是由于函数中已经存在同名的duckAge变量,所以需要通过this来访问数据成员duckAge

?
1
2
3
4
5
6
7
8
9
10
11
class Duck{
public:
    Duck(int age) { duckAge = age; };
    int getAge() { 
        int duckAge = 3;
            /// 通过this访问对象的数据成员duckAge,而不是局部变量duckAge
        return this->duckAge; 
    };
private:
    int duckAge;
};

4、指向类的非静态成员的指针

首先,类的静态成员和非静态成员是不同的,静态成员属于类,而非静态成员属于对象。指向类的非静态成员的指针,包含指向数据成员的指针和指向函数成员的指针。声明时需要指明指针指向的“类名”和“类型”,类型表示数据成员或函数成员的数据类型:

类型 类名::*数据成员指针名;
类型 (类名::*函数成员指针名)(参数表);

下面定义的Duck类包含public成员:int类型数据成员duckWeight和int类型函数成员getAge()(指向非静态成员的指针也必须遵守访问权限,不能指向private成员)下面分别声明指向二者的指针:

?
1
2
int Duck::*pointerDuckWeight;
int (Duck::*pointerGetAge)();

指向非静态成员的数据指针和函数指针赋值语法为:

数据成员指针名 = &类名::数据成员名;
函数成员指针名 = &类名::函数成员名;
下面对两个指针进行赋值:

?
1
2
pointerDuckWeight = &Duck::duckWeight;
pointerGetAge = &Duck::getAge;

上面进行的声明和赋值都是针对类进行的,所以并没有指向对象的成员地址。这里涉及到类的定义过程,类定义时并没有分配内存,而只是确定各个数据成员所占内存大小和相对位置。所以,可以使用对象的起始地址加相对位置对数据成员进行访问。非静态数据成员指针访问成员的语法有如下两种方式:

对象名.*数据成员的指针名
对象指针名->*数据成员指针名

?
1
2
/// 调用例子
printf("%d \n", duck.*pointerDuckWeight);

函数成员并不针对每个对象都有一个副本,而是共享的。对象调用函数成员时需要通过this指针,非静态成员函数指针的调用包含下面两种语法:

(对象名.函数成员指针名)(实参表)
(对象指针名->*函数成员指针名 )(实参表)

?
1
2
/// 实际调用的例子
printf("%d \n", (duck.*pointerGetAge)());

5、指向类的静态成员的指针

对于类的静态数据成员和函数成员,由于其并不属于具体的对象,所以只需要普通的数据型指针和函数型指针即可。

下面定义的Duck类包含用static声明的静态数据成员和静态函数成员:

?
1
2
3
4
5
6
7
8
class Duck{
public:
    static int getAge() { 
        return 666;
    };
    static int duckWeight;
};
int Duck::duckWeight = 333;

下面是指向类的静态成员的数据型指针和函数型指针的定义和赋值过程:

?
1
2
3
4
5
int *pointerDuckWeight;
int (*pointerGetAge)();
/// 赋值语法:指针名=&类名:静态成员名
pointerDuckWeight = &Duck::duckWeight;
pointerGetAge = &Duck::getAge;

调用指针的时候,只需要遵守基本数据型指针和函数型指针的调用语法即可:

?
1
2
printf("%d \n", *pointerDuckWeight);
printf("%d \n", (*pointerGetAge)());

到此这篇关于C++函数指针+对象指针+this指针+指向类静态和非静态成员的指针的文章就介绍到这了,更多相关C++指针内容请搜索服务器之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持服务器之家!

原文链接:https://zhuanlan.zhihu.com/p/104828038

延伸 · 阅读

精彩推荐
  • C/C++C语言 完整游戏项目推箱子详细代码

    C语言 完整游戏项目推箱子详细代码

    经典的推箱子是一个的古老游戏,目的是在训练你的逻辑思考能力。在一个狭小的仓库中,要求把木箱放到指定的位置,稍不小心就会出现箱子无法移动或...

    MAX在码字6472022-02-19
  • C/C++new和malloc的区别深入解析

    new和malloc的区别深入解析

    以下是分别是对new和malloc的区别进行了详细的分析及介绍,需要的朋友可以过来参考下...

    C语言教程网8602020-12-25
  • C/C++C++实现LeetCode(70.爬楼梯问题)

    C++实现LeetCode(70.爬楼梯问题)

    这篇文章主要介绍了C++实现LeetCode(70.爬楼梯问题),本篇文章通过简要的案例,讲解了该项技术的了解与使用,以下就是详细内容,需要的朋友可以参考下...

    Grandyang11552021-11-29
  • C/C++Linux系统中C语言编程创建函数fork()执行解析

    Linux系统中C语言编程创建函数fork()执行解析

    最近在看进程间的通信,看到了fork()函数,虽然以前用过,这次经过思考加深了理解。现总结如下...

    C语言教程网2772020-11-19
  • C/C++C语言实现支持动态拓展和销毁的线程池

    C语言实现支持动态拓展和销毁的线程池

    这篇文章主要为大家介绍了C语言实现支持动态拓展和销毁的线程池,感兴趣的小伙伴们可以参考一下...

    C语言教程网6702021-03-19
  • C/C++c++ map,mutimap删除问题分析

    c++ map,mutimap删除问题分析

    本文详细介绍c++ map,mutimap删除操作时的一些问题,提供了解决方法,需要的朋友可以参考下...

    C++教程网2762020-11-13
  • C/C++c语言调用汇编的方法

    c语言调用汇编的方法

    在此记录一下c调用汇编的方法,汇编使用的是AT&T语法。例子很简单,就是在给一个整数用汇编转换成二进制...

    C语言教程网8982021-01-09
  • C/C++OpenCV实现轮廓外接多边形

    OpenCV实现轮廓外接多边形

    这篇文章主要为大家详细介绍了OpenCV实现轮廓外接多边形,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...

    我有一個夢想6852021-11-17