函数指针
函数指针顾名思义即指向函数的指针。
函数指针定义和变量声明
返回类型 (*函数指针变量) (函数参数列表) = 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 |