【C++之指针】void指针、常量指针、指针数组、函数指针、对象指针、类成员指针

void指针

指针中,&为取地址运算符,负责取内存中的起始地址;而*:声明时为指针变量,对变量来说,是用于取地址所指向的内容
void类型的指针可以指向任意一种数据类型:void *p;
但是注意,
1、void类型指针赋值给一个有数据类型的指针时,需要进行强制转换:int *pint = static_cast<int*>(p);
2、无法通过void类型指针对所指对象进行访问和修改。
如下举例:直接通过void类型指针p对数组元素进行访问,会报错,而将p强制类型转换后再访问就成功。

int main() {
	void* p;
	p = new int[2]{ 1,2 };
	printf("%d", p[0]);//报错:表达式必须指向完整对象类型的指针
	printf("%d", static_cast<int*>(p)[0]);//正确输出1
}
常量指针

指向常量的指针,在指针变量声明时加上关键字const,例如定义一个常量指针p1指向a:const int *p1 = &a;,常量指针的特点是:指针本身可以改变,但是指针所指的对象不能修改,如下例子将会报错,无法改变p1所指对象a的值。

int main() {
	int a = 1;
	const int* p1 = &a;
	*p1 = 1;//报错
}
指针数组

先从数组来看,指向数组的指针假设定义如下:

int a[10], *pa;
pa=&a[0]; //或 pa = a;

则以下对数组元素的访问都是等效的:a[i], *(pa+i), *(a+i), pa[i],但是注意,不能写a++,因为a是数组首地址是常量。
而指针数组假设定义为:Point *pa[2],表示数组pa中的两个元素都是类Point的指针。

函数指针

指向函数的指针,就是指向程序代码存储区,
声明形式:存储类型 数据类型 (*函数指针名)();
举例如下,函数指针funcPointer指向函数printMessage并调用,
注意:指针所指向的对象是有限制的,返回值类型要相同,且参数类型和个数要对应,否则无法指向。

void printMessage(string s, int month) {
	printf("%s,今天是%d月\n", s.c_str(), month);
}

int main() {
	void (*funcPointer)(string,int);//函数指针
	funcPointer = printMessage;
	funcPointer("你好", 3);
}
对象指针

指向类的对象的指针,声明形式为:类名 *对象指针名;例如:

Point a(5,10);
Point *pa = &a;

其中要调用到类Point的成员时,要用到符号“->”,例如pa->getX();
有一种情形,类A与类B相互引用,错误方法如下:

class B;
class A {
	B b;//报错,使用了未定义的class B
};
class B {
	A a;
};

可以利用对象指针来解决报错,如下所示,为在类A中为类B设定一个对象指针,在类B还未完整声明之前,类B的对象指针首先指向一个确定的地址即可。

class B;
class A {
	B *b;//正确
};
class B {
	A a;
};
类成员指针

1、this指针明确地指出了成员函数当前所操作的数据所属的对象。机制为,当通过一个对象调用成员函数时,系统先将该对象的地址赋给this指针,然后调用成员函数,成员函数对对象的数据成员进行操作时,就隐含地使用了this指针。
2、指向类的非静态成员的指针:通过指向成员的指针只能访问到公有成员。
(1)指向数据成员的指针方法:
- 声明指向公有数据成员的指针:类型说明符 类名:: *指针名;
- 说明指针应该指向哪个成员:指针名 = &类名::数据成员名;
- 通过对象名(或对象指针)与成员指针结合来访问数据成员:

对象名.*类成员指针名
对象指针名->*类成员指针名

(2)指向函数成员的指针方法:
- 声明指向公有函数成员的指针:类型说明符 (类名:: * 指针名)(参数表)
- 说明指针应该指向哪个成员:指针名 = &类名::数据成员名
- 通过对象名(或对象指针)与成员指针结合来访问数据成员:

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

举例如下:其中注意在函数成员指针赋值时,指向的函数成员中不需要加括号()

class A {
public:
	int x;
	int getX() {
		return x;
	}
};
int A::* px = &A::x;//定义了类的非静态数据成员指针
int(A::* pGetX)() = &A::getX;//定义了类的非静态函数成员指针
int main() {
	A a;
	A* pa = &a;
	a.x = 1;
	printf("%d %d\n", a.*px, pa->*px);//两者同
	printf("%d %d\n", (a.*pGetX)(), (pa->*pGetX)());//两者同
}
/*输出:
1 1
1 1
*/

3、指向类的静态成员的指针
与上面不同,对类的静态成员的访问不依赖于对象,因为可以用普通的指针来指向和访问静态成员,举例如下:

class A {
public:
	static int x;
	static int getX() {
		return x;
	}
};
int A::x = 1;

int main() {
	int* px = &A::x;//指向静态数据成员的指针
	int (*funcPtr)() = A::getX;//指向静态函数成员的指针
	printf("%d %d", *px, funcPtr());
}
/*输出:
1 1
*/
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值