欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

由浅入深讲解动态类函数指针

程序员文章站 2024-03-20 22:18:58
...

1、首先描述一下指针值的含义: 

假设内存值的序列是这样描述的 : 我们定义一个 0 ~ 50 的正整数序列。

                                                       0,0,0,0,0,0,0,0,0,0,

                                                       0,0,0,0,1,0,0,8,0,0,

                                                       0,0,0,0,0,0,0,0,0,0,

                                                       0,0,0,0,0,0,0,0,0,0,

                                                       0,0,0,0,0,0,0,0,0,0

它第15号数值是 1,第18号数值是8。

由此,我们可以想象 “序号15” 就是指针,指针的值就是 “序号15位置上描述了一个变量1”。

为了方便表示:我们定义变量 x 的位置就在 “序号15”上,y序号的位置就在”序号18”上。

 

                                                        所以其值相加:x + y = 1 + 8 = 9;

 

为了刻意记录这些序号位置,我们又创建了一张表专门记录这些序号,它的描述方式假设是这样的:

(为了文章的简洁性:我们将描述这些变量的值 用 n(x) 来表式, & 表示向上取这些值的序号位置 )

                                          &n0  ,&n1  ,&n2  ,&n3  ,&n4  ,&n5  ,&n6  ,&n7  ,&n8  ,&n9 ,

                                          &n10,&n11,&n12,&n13,&n14,&n15,&n16,&n17,&n18,&n19,

                                          &n20,&n21,&n22,&n23,&n24,&n25,&n26,&n27,&n28,&n29,

                                          &n30,&n31,&n32,&n33,&n34,&n35,&n36,&n37,&n38,&n39,

                                          &n40,&n41,&n42,&n43,&n44,&n45,&n46,&n47,&n48,&n49

“序号15”位置上描述了一个变量1,我们可以理解成,记录 “序号15值”的变量是1,其变量名是”n15”,记录n15的位置是”&n15”(第15号地址);

因 ”&表示获取序号” ,那么它的反作用 ”*表示取序号下的值”所以:

                                                                                 *(&n15) = n15 = 1;

 

扩展理解【假设: *n15 = *(&1); (这里是把n15 的值当做一个地址来使用,它表示第1号地址的值)】

2、由于本文章强调的是动态函数指针传递,那么我们进入正题:(关于指针的其他问题可以在评论区提问)

//例子1 运行基本实例 (动态函数指针的传递)
class T_object
{
public:
	T_object(){
	}
	virtual ~T_object(){
	}
	int func(void* p){
		int step = *((int*)p);
		step += 2;
		return step;
	}
};

void main()
{
	T_object t;
	int (T_object::* _pfunc) (void*) = &T_object::func;
	int step = 0;
	for (size_t i = 0; i < 100; i++)
	{
		step = (t.*_pfunc)(&step);
		printf("running T_object::func,%d\n", step);
	}
}

将动态函数指针赋予 _pfunc 作为载体,它需要 t 对象完成实例化执行。

执行方法如下:

step = (t.*_pfunc)(&step); 
step = t.func(&step);

这两个等式表达方式是一样的。

(关于用途举例:可以在主类不采用多态的方式承载多套实现的方法,这里引用敲门砖,希望大家能够举一反三)

//例子2 动态函数指针的应用
class T_object
{
public:
	T_object(){
	}
	virtual ~T_object(){
	}
	int func(void* p){
		int step = *((int*)p);
		step += 2;
		return step;
	}
//new coode begin
	int func1(void* p) {
		int step = *((int*)p);
		step += 3;
		return step;
	}
	int func2(void* p) {
		int step = *((int*)p);
		step += 4;
		return step;
	}
//new coode end
};

void main()
{
	T_object t;
	int (T_object::* _pfunc) (void*) = &T_object::func;
	_pfunc = &T_object::func1;
	_pfunc = &T_object::func2;
	int step = 0;
	for (size_t i = 0; i < 100; i++)
	{
		step = (t.*_pfunc)(&step);
		printf("running T_object::func,%d\n", step);
	}
}

以上调用仅表示它最基本的原始代码展现,方便认知阅读:

(为了提高阅读使用性,下面我们开始优化变型操作)

将函数式包含在内,使调用方更易理解及调用;

//例子3 函数指针作为参数传递
class T_object
{
public:
	T_object(){
		m_pfunc = NULL;
	}
	virtual ~T_object() {
	}
	int func(void* p){
		int step = *((int*)p);
		step += 2;
		return step;
	}
	void addfunc(int(T_object::* pfunc)(void*))
	{
		m_pfunc = pfunc;
	}
	int Do(int step)
	{
		if (m_pfunc != NULL)
		{
			step = (this->*m_pfunc)(&step);
		}
		return step;
	}
	int(T_object::* m_pfunc)(void*);
};

void main()
{
	T_object t;
    //添加函数指针 (对外的方法及调用)
	t.addfunc(&T_object::func);
	int step = 0;
	for (size_t i = 0; i < 100; i++){
		step = t.Do(step);
		printf("running T_object::func,%d\n", step);
	}
}

根据此方法,可以动态的实施类函数的调用。

将函数指针式再简化,函数指针作为命名类型参数传递:

//例子 4 函数指针作为命名类型参数传递
class T_object
{
public:
	//定义函数类
	typedef int(T_object::* PFUNC)(void*);
	T_object() {
		m_pfunc = NULL;
	}
	virtual ~T_object() {
	}
	int func(void* p) {
		int step = *((int*)p);
		step += 2;
		return step;
	}
	void addfunc(PFUNC pfunc)
	{
		m_pfunc = pfunc;
	}
	int Do(int step)
	{
		if (m_pfunc != NULL)
		{
			step = (this->*m_pfunc)(&step);
		}
		return step;
	}
	PFUNC m_pfunc;
};
 
void main()
{
	T_object t;
    //添加函数指针 (对外的方法及调用)
	t.addfunc(&T_object::func);
	int step = 0;
	for (size_t i = 0; i < 100; i++){
		step = t.Do(step);
		printf("running T_object::func,%d\n", step);
	}
}

以上是关于类函数传参的调用方式,可以通过该方法实现很多功能,内容太多本次就不一一举例了。

相关标签: 代码 技术文档