c++函数指针和类的成员函数指针及其大小

函数指针

函数指针顾名思义即指向函数的指针。

函数指针定义和变量声明

返回类型 (*函数指针变量) (函数参数列表) = func;

typedef 返回类型 (*函数指针类型) (函数参数列表);

实际例子:


// 测试函数
int testInt(int a, int b)
{
	std::cout << "a=" << a << " b=" << b << std::endl;
	return a + b;
}

int _tmain(int argc, _TCHAR* argv[])
{
	// 定义函数指针变量fnInt1并对其赋值
	int (*fnInt1)(int a, int b) = testInt;
	(*fnInt1)(1, 2);	// 输出结果:a=1 b=2
	std::cout << "fnInt1=" << sizeof(fnInt1) << std::endl;	// 输出结果:fnInt1=4

	// 定义指向 int(*)(int, int)的函数指针类型 funcInt2
	typedef int (*funcInt2)(int a, int b);
	// 定义函数指针变量fnInt2并赋值
	funcInt2 fnInt2 = testInt;
	(*fnInt2)(2, 3);	// 输出结果:a=2 b=3
	std::cout << "fnInt2=" << sizeof(fnInt2) << std::endl;	// 输出结果:fnInt2=4
	return 0;
}

总结函数指针的大小为4。

类成员函数指针

类成员函数指针即指向类成员函数的指针

定义方式:

返回类型 (类名*函数指针变量) (函数参数列表) = &类名::函数;

void (BaseVirt::*fnbv)(int) = &BaseVirt::func0;

fnbv 为 指向类BaseVirt的成员函数的指针。

用法:

(类对象指针->*函数指针变量)(函数参数列表);

BaseVirt *pbv;

(pbv->*fnbv)(2);

定义类成员类型的指针类型和变量声明:

typedef 返回类型 (类名*函数指针类型) (函数参数列表);

函数指针类型  函数指针变量 = &类名::函数;

typedef void (BaseVirt::*funcBV)(int);

funcBv fnbv = &BaseVirt::func0;

funcBV 为 指向类BaseVirt的成员函数的类型。

fnbv 为 指向类BaseVirt的成员函数的指针。

用法:

BaseVirt *pbv;

(pbv->*fnbv)(2);

接下来看看各个指针的大小,上代码。


// 没有虚函数的基类
class BaseNoVirt
{
public:
	BaseNoVirt() { m_a = 0; }
	~BaseNoVirt() { }
	void func0(int a) {
		std::cout << "BaseNoVirt func0. a = "<< a << std::endl;
	}
protected:
	int m_a;
};

// 没有虚函数的基类
class BaseVirt
{
public:
	BaseVirt() { m_a = 0; }
	~BaseVirt() { }
	virtual void func0(int a) {
		std::cout << "BaseVirt func0. a = "<< a << std::endl;
	}
protected:
	int m_a;
};

// 继承没虚函数的类型,自己没虚函数
class CNoNo : public BaseNoVirt
{
public:
	CNoNo() { }
	~CNoNo() { }
	void func2() {}
};

// 继承没虚函数的类型,自己有虚函数
class CNoVirt : public BaseNoVirt
{
public:
	CNoVirt() { }
	~CNoVirt() { }
	virtual void func2() {}
};

// 继承有虚函数的类型,自己没虚函数
class CVirtNo : public BaseVirt
{
public:
	CVirtNo() { }
	~CVirtNo() { }
	virtual void func2() {}
};

// 继承有虚函数的类型,自己有虚函数
class CVirtVirt : public BaseVirt
{
public:
	CVirtVirt() { }
	~CVirtVirt() { }
	virtual void func2() {}
};

class CMul : public BaseNoVirt, public BaseVirt
{
public:
	CMul() { }
	~CMul() { }
	virtual void func2() {}
};

// 测试类成员函数指针的函数
void testClassMemberFuncPtr()
{
	// 基类成员函数指针
	void (BaseNoVirt::*fnbNv)(int) = &BaseNoVirt::func0;
	BaseNoVirt bnv, *pbnp = &bnv;
	// 输出结果:BaseNoVirt func0. a = 2
	(pbnp->*fnbNv)(2);
	// 定义funcBV类的类成员指针
	typedef void (BaseVirt::*funcBV)(int);
	funcBV fnbv = &BaseVirt::func0;
	BaseVirt bv, *pbv = &bv;
	// 输出结果:BaseVirt func0. a = 3
	(pbv->*fnbv)(3);
	// 输出结果:BaseNoVirt memberPtr size=4
	std::cout << "BaseNoVirt memberPtr size=" << sizeof(fnbNv) << std::endl;
	// 输出结果:BaseVirt memberPtr size=4
	std::cout << "BaseVirt memberPtr size=" << sizeof(fnbv) << std::endl;
	// 输出结果:CNoNo memberPtr size=4
	std::cout << "CNoNo memberPtr size=" << sizeof(&CNoNo::func2) << std::endl;
	// 输出结果:CNoVirt memberPtr size=8
	std::cout << "CNoVirt memberPtr size=" << sizeof(&CNoVirt::func2) << std::endl;
	// 输出结果:CVirtNo memberPtr size=4
	std::cout << "CVirtNo memberPtr size=" << sizeof(&CVirtNo::func2) << std::endl;
	// 输出结果:CVirtVirt memberPtr size=4
	std::cout << "CVirtVirt memberPtr size=" << sizeof(&CVirtVirt::func2) << std::endl;
	// 输出结果:CMul memberPtr size=8
	std::cout << "CMul memberPtr size=" << sizeof(&CMul::func2) << std::endl;

	// 当成员函数指针所在的类是未知时,其指针大小是16
	class unkownClass;
	typedef void (unkownClass::*fnUnkownClass)(void);
	std::cout << "unkownClass memberPtr size=" << sizeof(fnUnkownClass) << std::endl;
}

根据上述代码运行发现,类成员函数指针的大小主要和类是否有虚函数以及该类是否被识别有关。

总结如下表:

类成员函数指针大小
基类情况本类情况大小
无继承的类,其成员函数指针大小4
没虚函数没虚函数4
没虚函数有虚函数

8

有虚函数没虚函数4
有虚函数有虚函数4
有多重继承类,不管基类或自己是否虚函数都一样8
无法识别的类的成员函数指针16

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值