C
C语言中没有类的概念,只有普通的函数。通过函数名就可以得到函数地址
#include <stdio.h> #include <stdlib.h> void fun() { } int main() { printf(
"%p\n", &fun); }
对于 fun 和 &fun 应该这样理解:

fun 是函数的首地址,它的类型是 void ()
&fun 表示一个指向函数 fun 这个对象的地址, 它的类型是 void (*)()
因此 fun 和 &fun 所代表的地址值是一样的,但类型不一样。

fun 是一个函数
&fun 表达式的值是一个指针!

C++
普通函数
C++的普通函数和C中是一样的,利用函数名就可以获得函数地址。

类静态函数
本类所有对象公用一个静态函数,所以是同一个地址【其实类的成员函数都只有一个,解释见后文】。和普通函数一样,有了函数名就可以获得地址。
可以用类名::函数名,也可以用对象.函数名 / 对象指针->函数名。

类成员函数(除了静态函数外的所有类中的函数)

有这样一个类:
class Base { public: Base() { cout << "Base构造" << endl; } virtual ~Base() {
cout<< "Base虚析构" << endl; } virtual void f1() { cout << "Base::f1()" << endl; }
void f2() { cout << "Base::f2()" << endl; } virtual void f3() { cout <<
"Base::f3()" << endl; //cout << data << endl; } int data = 5; static void fn() {
} };
如果这样输出:
cout << &Base::f1 << endl; // 普通类成员函数 cout << &Base::f2 << endl; // 虚函数 //
cout << &p->f1 << endl; // cout << &p->f2 << endl; // 这两个都会报错,对象绑定的函数只能用于调用
那么输出结果都是 :1。明显不是函数地址值。

首先分析一下这几种成员函数在运行机制的不同

静态函数,是独立于对象的,是类拥有的,所以我们调用静态函数,既可以通过类调用也可以通过对象调用。无论是通过类调用还是对象调用,对应的都是同一个函数。

动态函数,只能通过对象来调用。因为在动态成员函数中,往往都需要访问对象的成员变量。我们知道同一类型的不同对象,它们拥有类中成员变量的不同副本,所以假如动态成员函数由类来调用,我们无法知道在函数中访问的是哪一个对象的成员变量。

要输出动态函数的地址,必须通过对象来获取。

C++调用非静态的成员函数时,采用的是一种 __thiscall
的函数调用方式。采用这种调用方式,编译器在编译的时候,会在调用的函数形参表中增加一个指向调用该成员函数的指针,也就是我们经常说的this指针。调用的形式类似于Base::f1(Base*
this,
otherparam…),在函数体中,涉及到对象的成员变量或者其他成员函数,都会通过这个this指针来调用,从而达到在成员函数中处理调用对象所对应的数据,而不会错误处理其他对象的数据。可见,虽然我们必须通过对象来调用动态函数,但是其实我们访问的都是同一个成员函数。所以我们采用&Base::f1来获取成员函数地址是没错的,动态函数同样是跟类绑定而不是跟对象绑定的。

出错的原因是,输出操作符<<没有对void(__thiscall A:: *)()类型重载,编译器将这种类型转换为bool类型,所以输出了1;

对于静态函数,其调用方式并非__thiscall,<<有对它的重载,因此类的静态函数可以直接用cout输出函数地址。我们可以用printf输出,因为他可以接收任意类型的参数,包括__thiscall类型
cout << p->fn << endl; // 静态成员函数可以直接获取地址 cout << Base::fn << endl; //
静态成员函数可以直接获取地址 cout << &Base::f1 << endl; // 编译器将void(__thiscall
A::*)()类型转换为bool类型。 输出 1 printf("Base::f1()地址:%p\n", &Base::f1); printf(
"Base::f2()地址:%p\n", &Base::f2); printf("Base::fn()地址:%p\n", &Base::fn);

技术
今日推荐
下载桌面版
GitHub
百度网盘(提取码:draw)
Gitee
云服务器优惠
阿里云优惠券
腾讯云优惠券
华为云优惠券
站点信息
问题反馈
邮箱:[email protected]
QQ群:766591547
关注微信