C++类成员变量指针和类成员函数指针、nullptr的底层实现

C++中指向类成员变量指针和成员函数指针的定义方法

我们知道,如果我们需要在C++中用到关于类成员的函数或者变量,就必须使用域运算符。那么我们该如何定义指向类成员变量的指针呢?
格式为:类型名(类名::*指针名) = &类名::类的成员变量名
成员变量指针调用:对象名.*成员变量指针名
我们通过下面的简单程序来认识它:

class Myclass
{
public:
	Myclass(const char* a)
	{
		this->str = new char[strlen(a) + 1];
		strcpy(str, a);
	}
	char* c_str()
	{
		return str;
	}

public:
	char* str;
};

int main()
{
	char* (Myclass::* ptr) = &Myclass::str;
	Myclass m1("abcdef");
	cout << m1.*ptr << endl;
	return 0;
}

运行结果:
在这里插入图片描述
我们可以得出结论:m1.*ptr 等效于m1.str。

那么如何来定义指向类成员函数的指针呢?
类型名 (类名::*指针名)(参数类型表) = &类名::类的成员函数名
成员函数指针调用:(对象名.*成员函数指针名)(实参表)

 class Myclass

{
public:
	Myclass(const char* a)
	{
		this->str = new char[strlen(a) + 1];
		strcpy(str, a);
	}
	char* c_str()
	{
		return str;
	}
public:
	char* str;
};

int main()
{
	Myclass m1("abcde");
	char*(Myclass::*ptr)() = &Myclass::c_str;
	cout<<(m1.*ptr)();
	return 0;
}

运行结果:
在这里插入图片描述
我们可以看出前面的调用用到非指针对象调用的 .* 和 指针对象调用使用的->*符号。那么,如何不使用这些符号而调用到那些函数呢?我们可以通过bind函数来进行绑定的操作。其中bind函数可以使用占位符和默认参数,如果需要使用占位符就需要引用命名空间std::placeholder。

int main()
{
	Myclass m1("abcde");
	auto fun = bind(&Myclass::c_str, &m1);
	cout<<fun();
	return 0;
}

nullptr的底层实现

那么能举个类成员函数指针的应用场景吗?我首先想到的就是C++2.0的nullptr了。为什么要引用nullptr呢?咱们这里简单的说一下。

C++中允许将 0 赋值给任意指针类型,但是 0 也可以赋值给普通的变量。那么,对于C++这种强类型的语言,它怎么来进行普通变量和指针之间的区分呢?
其实就是封装一个类,并生成一个object(nullptr)。这个类内部用函数模板实现了一个可以将 0 值赋值给指针类型的变量,但是不可以赋值给普通类型,作为改进的空指针版本。下面我们看具体实现:(注意:用到了上面学到的类成员变量和成员函数指针)
补充说明一点:
operator type*()函数,其实就是当改类的变量赋值给 type* 类型指针的时候就会调用到该函数。

class MyNULL
{
public:
	//这个函数是允许将该类的对象赋值给普通指针
	template<class T>
	inline operator T*() { return 0; }
	//允许将类的对象赋值给类成员变量和类成员函数类型
	//其中 T 表示的是类的类型,V代表的是变脸类型(成员变量)或者返回值类型(成员函数)
	template<class T, class V>
	inline operator V T::*() { return 0; }
};

下面是测试代码:

int main()
{
	MyNULL nullptr_m;
	//定义普通指针
	int* a = nullptr_m;
	double* b = nullptr_m;
	float* c = nullptr_m;
	Myclass* d = nullptr_m;
	//指向类成员函数的指针
	int(Myclass::*ptr)() = nullptr_m;
	//指向类成员变量的指针
	int Myclass::*pointer = nullptr_m;
	//定义类成员变量指针的引用
	int Myclass::*&rpointer = pointer;

	//error!!!!!!!!这样就可以区分普通可以赋值为 0 的类型和空指针类型都是0的情况了
	int a = nullptr_m;
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值