C++知识点杂记2——类成员指针、嵌套类和union

本文详细讲解了类成员指针的概念,包括成员变量指针和成员函数指针的使用、访问权限与限制,以及嵌套类的作用和应用场景。通过实例演示,深入理解指针在C++中的实际操作。

一、类成员指针

1.概念

类成员指针指向的是类的非static成员,因为类的static成员是所有类对象共有,所以static成员的指针和普通指针没有区别

 

2.成员变量指针

示例

class test
{
public:
	test(){}
	~test(){}
	int pub;

private:
	int pri;
};

int main(int argc, char const *argv[])
{
	int test::*pi=&test::pub;
	test t;
	t.*pi=10;
	cout<<t.pub<<endl;
	return 0;
}

上述代码中pi就是个test的成员变量指针,成员变量指针的读法依旧是从右到左,首先*pi知道pi是个指针,::test知道该指针指向test对象中的成员,int表明该指针指向test对象中的int成员

因为成员变量指针是个指针,解引用需要用*,但是该指针又指向某个类的成员变量。所以不能直接解引用类成员指针,必须用类的对象,指针或者引用访问该成员变量指针解引用出来的成员变量

如果把t.*pi=10;写成*pi,将会出错

提示解引用无效,因为没有指定访问该解引用的类的对象,指针或者引用

 

成员变量有访问权限,所以,成员变量的指针也受访问权限修饰符的影响,上述代码中,不能在主函数中让一个成员变量指针指向&test::pri,因为pri是private的,否则会出现如下错误

对于私有的成员变量指针,只能在类的成员和友元中使用

 

因为成员变量一般是私有的,所以一般不能直接获取成员指针,需要一个返回成员指针的函数

示例

class test
{
public:
	test(){}
	~test(){}
	int pub;
	int test::*funcpri();

private:
	int pri;
};

int test::*test::funcpri()//返回一个成员变量指针的函数
{
	return &test::pri;
}

int main(int argc, char const *argv[])
{
	test t;
	int test::*p=t.funcpri();
	t.*p=10;
	cout<<t.*t.funcpri()<<endl;//打印对象t的pri成员
	return 0;
}

 

3.成员函数指针

成员函数指针用的比较多的就是用作Qt的信号槽,和成员变量指针、函数指针类似

示例

connect(pstartbtn_, &QPushButton::pressed, this, &MainWindow::onstartbtnclicked);
connect(pkeyboardbtn_, &QPushButton::pressed, this, &MainWindow::onkeyboardclicked);

上述代码中,connect的第2个和第4个参数就是成员函数指针,成员函数不能自动转化为成员函数指针,所以必须在成员函数前加上&,得到的才是成员函数指针

 

和成员变量一样,因为成员函数指针是个指针,解引用需要用*,但是该指针又指向某个类的成员函数。所以不能直接解引用类的成员函数指针

必须用类的对象,指针或者引用访问该成员函数指针解引用出来的成员函数

示例

class test
{
public:
	test(){}
	~test(){}
	void func() const{};
};

int main(int argc, char const *argv[])
{
	test t;
	void (test::*pf)() const=&test::func;
   (t.*pf)();
	return 0;
}

上述代码中第12行中,(test::*pf)中的括号和后面的const必不可少

此外。13行中的(t.*pf)();不能写成t.*pf();当把括号去掉后,编译器就认为要调用一个名字叫pf的成员函数,然而pf并不是成员函数,于是报错

成员函数有访问权限,所以,成员函数的指针也受访问权限修饰符的影响,同成员变量

 

想通过成员函数指针进行函数调用,必须通过将该成员函数指针绑定到特定的对象、指针或引用上。所以,单独的成员函数指针并不是可调用对象,所以,不能直接将单独的成员函数指针作为实参传入一个函数

示例

int main(int argc, char const *argv[])
{
	vector<string> vstr={"123", "456", "789"};
	bool (string::*p)() const= &string::empty;
	find_if(vstr.begin(), vstr.end(), p);
	return 0;
}

所以,当使用函数指针作为参数时,不要把成员函数指针当做实参,因为成员函数指针不可调用

 

二、嵌套类

顾名思义就是一个类定义在另一个类的内部。嵌套类的名字只在外层类中可见,在其他地方不可见。虽然嵌套类在另一个类中定义,但是和外层类没有任何关系,只不过作用域仅限于外层类

示例

class one
{
public:
	one(){}
	~one(){}

	class two
	{
	public:
		two(){}
		~two(){}
		void func2();
		int twomem;
	};
};

void one::two::func2() {}
int main(int argc, char const *argv[])
{
	//two t;
	//one t;
	//t.func2();
	return 0;
}

two是one的嵌套类,当实现two中的func2时,func2的作用域也是从外到内一层一层写。因为two的作用域仅限于one,所以20行的代码是错误的,因为one和two没有任何关系,所以2122行的代码是错误的

因为嵌套类的作用域仅限于外层类。所以,嵌套类一般用于外层类的实现

 

三、union

union有多个数据成员,但是这些数据共用内存,同一时刻只有一个成员有值

union在嵌入式开发中非常常用,经常和char数据一起使用,用来定义收发数据的数据格式

示例

union uploaddata 
{
	unsigned char buffer[20];
	
	struct sensorstr
	{
		unsigned int Header;
		float X_speed;
		float Y_speed;
		float Z_speed;
		unsigned char End_flag;
	}sensordata;
};

union中buffer的大小正好就是sizeof(sensordata),buffer和sensordata共用一块内存,当收到buffer中的数据时,可以通过struct对buffer中的数据进行解析,当发送数据时,也可以通过对struct的成员进行赋值,然后将buffer发送出去

 

参考

《C++ Primer》

 

欢迎大家评论交流,作者水平有限,如有错误,欢迎指出

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值