下面讨论的都是类的非静态成员函数。

类成员函数指针的声明及调用:

1
2
3
4
5
6
7
//pr是指向Base类里的非静态成员函数的指针
//其行参为(int, int),返回值为void
void (Base::*pr)(int, int);
 
//需通过对象调用
//object是Base类的一个对象或指针(可多态)
( object->*pr)( _r, _c)

而其实质和普通的指针也有区别:

//下面是隐藏的代码是相关类型的定义

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
void Foo1(int a, int b, int c)
{
    return;
}
 
void Foo2(int a, int b)
{
    return;
}
 
class Base{
public:
    void Foo3(int a, int b, int c)
        {return;}
    void Foo3(int a,int b)
        {return;}
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include<iostream>
using namespace std;
 
int main()
{
    void (Base::*p1)(int,int,int) = &(Base::Foo3);
    void (Base::*p2)(int,int) = &(Base::Foo3);
    void (Base::*p3)(int,int,int) = NULL;
    cout<<"Foo1: "<<Foo1<<'\t'<<sizeof(&Foo1)<<'\n'
        <<"Foo2: "<<Foo2<<'\t'<<sizeof(&Foo2)<<'\n'
        <<"p1:   "<<p1<<'\t'<<sizeof(p1) <<'\n'
        <<"p2:   "<<p2<<'\t'<<sizeof(p2) <<'\n'
        <<"p3:   "<<p2<<'\t'<<sizeof(p3) <<endl;
}

输出结果为:

Foo1: 00BB1510  4 
Foo2: 00BB1520  4 
p1:   1 4 
p2:   1 4 
p3:   0 4

从结果上来看,指向成员函数的指针值均为1。且在调试过程中可以看到:

p1    error: cannot obtain value    void*

p2    error: cannot obtain value    void*

p3    error: cannot obtain value    void*

但这个指针指向的函数实际上是可以被调用的。

搜索之,看到了一篇文章:

http://blog.csdn.net/hairetz/archive/2009/05/06/4153252.aspx

1。成员函数指针不是指针。从代码看出,在main函数的调用栈(calling stack)中首先依次压入四个成员函数指针,如果它们是普通指针的话,它们之间的偏移量应该是4个字节,可是实际的情况却是这样的:

”The implementation of the pointer to member function must store within itself information as to whether the member function to which it refers is virtual or nonvirtual, information about where to find the appropriate virtual function table pointer (see The Compiler Puts Stuff in Classes [11, 37]), an offset to be added to or subtracted from the function's this pointer (see Meaning of Pointer Comparison [28, 97]), and possibly other information. A pointer to member function is commonly implemented as a small structure that contains this information, although many other implementations are also in use. Dereferencing and calling a pointer to member function usually involves examining the stored information and conditionally executing the appropriate virtual or nonvirtual function calling sequence.“

这篇文章较深入地研究了成员函数指针,及比较了普通成员函数指针和虚函数指针在转化的过程中存在那些差异。

类成员函数指针的特殊之处(成员函数指针不是指针,内含一个结构体,需要存储更多的信息才能知道自己是否virtual函数)的更多相关文章

  1. NX二次开发-如何在类外面定义一个结构体

    #include <uf.h> #include <uf_obj.h> #include <uf_part.h> using namespace NXOpen; u ...

  2. (C/C++) 用函数返回一个结构体

    方法一: 参数里含有指向指针的指针. 注意:如果函数参数里只有一个指向结构体的指针,是无法正确地返回结构体的值的.原因在于在编译的时候,会对入参p产生一个备份_p. 参考此文:http://www.c ...

  3. QMap的key也可以是一个结构体类吗?

    QMap<usbsnvidpid, QVector<QString>> USBVIDPIDTIME; USBVIDPIDTIME.insert(m_vidpidsn, time ...

  4. 由结构体成员地址计算结构体地址——list_entry()原理详解

    #define list_entry(ptr, type, member) container_of(ptr, type, member) 在进行编程的时候,我们经常在知道结构体地址的情况下,寻找其中 ...

  5. OC对象里面包含的结构体类型的属性,不能对该结构体属性的成员单个进行修改

    OC对象里面包含的结构体类型的属性,不能对该结构体属性的成员单个进行修改,需要对OC对象的结构体属性整体赋值. 关于网上很多博客写着“结构体类型里面的某个属性如果想要修改是不允许单个修改的” 之解释: ...

  6. 深入理解指针—>结构体里的成员数组和指针

    单看这文章的标题,你可能会觉得好像没什么意思.你先别下这个结论,相信这篇文章会对你理解C语言有帮助.这篇文章产生的背景是在微博上,看到@Laruence同学出了一个关于C语言的题,微博链接.微博截图如 ...

  7. 读陈浩的《C语言结构体里的成员数组和指针》总结,零长度数组

    原文链接:C语言结构体里的成员数组和指针 复制例如以下: 单看这文章的标题,你可能会认为好像没什么意思.你先别下这个结论,相信这篇文章会对你理解C语言有帮助.这篇文章产生的背景是在微博上,看到@Lar ...

  8. 全面总结sizeof的用法(定义、语法、指针变量、数组、结构体、类、联合体、位域位段)

    一.前言 编译环境是vs2010(32位). <span style="font-size:18px;">#include<iostream> #inclu ...

  9. C++,关于类和结构体中,成员访问属性(public,private)

    今天发现一个的问题: #include <vector> #include <iostream> #include <algorithm> #include < ...

随机推荐

  1. 第二十一篇:基​于​W​D​M​模​型​的​A​V​S​t​r​e​a​m​驱​动​架​构​研​究

    基​于​W​D​M​模​型​的​A​V​S​t​r​e​a​m​驱​动​架​构​研​ 这篇论文2006年早就发表, 与当时开发这个驱动正好几乎相同的时间. 近期实际项目须要, 又回过头来将AVStre ...

  2. Android菜鸟的成长笔记(23)——获取网络和SIM卡信息

    TelephonyManager是一个管理手机通话状态.电话网络信息的服务类,该类提供了大量的getXxx()方法来获取电话网络的相关信息.这些信息包括设备编号.软件版本.网络运营商代号.网络运营商名 ...

  3. XMPP开发adiumclient登陆

    我写在前面client它已经实现了登陆,我用下面的adium要登录落实的朋友加入,而自己写的client在聊天帐号. 第一次登录时adium工欲善其事,必先例如,下面的配置 保存后.你会发现自己的账号 ...

  4. .net remoting 使用事件

    原文:.net remoting 使用事件 在RPC如果需要使用事件,相对是比较难的.本文告诉大家如何在 .net remoting 使用事件. 目录 使用 Channel 序列化 开发建议 修复异常 ...

  5. HashMap工作原理的介绍!

    HashMap的工作原理是近年来常见的Java面试题.几乎每个Java程序员都知道HashMap,都知道哪里要用HashMap,知道HashTable和HashMap之间的区别,那么为何这道面试题如此 ...

  6. s3c2410 cs8900a 网卡驱动程序

    /* CS8900a.h */ #define CONFIG_CERF_CS8900A 1 /* * cs8900a.c: A Crystal Semiconductor (Now Cirrus Lo ...

  7. 工作流管理平台Airflow

    Airflow 1. 引言 Airflow是Airbnb开源的一个用Python写就的工作流管理平台(workflow management platform).在前一篇文章中,介绍了如何用Cront ...

  8. UVA - 10312 Expression Bracketing

    Description Problem A Expression Bracketing Input: standard input Output: standard output Time Limit ...

  9. Visual C# 2010 实现菜单项和状态栏

    演练:向窗体提供标准菜单项 Visual Studio 2010     其他版本     此主题尚未评级 - 评价此主题   可以通过 MenuStrip 控件为窗体提供标准菜单. 此演练演示如何使 ...

  10. 基于WPF实现双色球

    原文:基于WPF实现双色球 版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.net/m0_37591671/article/details/82959625 ...