C++ 函数指针

C


  • C语⾔中没有类的概念,只有普通的函数。通过函数名就可以得 到函数地址
#include <stdio.h>
#include <stdlib.h>
void fun() {
}
int main() {
    printf("%p\n", &fun);
}
  • 对于 fun &fun 应该这样理解:
  1. fun 是函数的⾸地址,它的类型是 void ()
  2. &fun 表示⼀个指向函数 fun 这个对象的地址, 它的类型是 void (*)()
  • 因此 fun &fun 所代表的地址值是⼀样的,但类型不⼀ 样。
  1. fun 是⼀个函数
  2. &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);

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

chls

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值