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

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

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. Linux之定时任务Crond介绍

    Linux之定时任务 定时任务Crond介绍 Crond是linux系统中用来定期执行命令/脚本或指定程序任务的一种服务或软件,一般情况下,我们安装完Centos5/6 linux操作系统之后,默认便 ...

  2. Vuex的一个易错点

    好长时间不用Vuex,发现有些东西记模糊了. 在对Vuex进行模块化开发的时候, const store = new Vuex.Store({ modules: { a: moduleA, b: mo ...

  3. Cordova/PhoneGap 安卓开发环境搭建

    此文为个人原创作品,如有不正确之处,恳请大家指出,并请您谅解,转载请说明出处. 准备阶段: 必备: JDK(根据自己的开发平台下载相应的安装包,可能需要FQ) Nodejs  (根据自己的开发平台下载 ...

  4. Session Redis Nginx

    Session + Redis + Nginx 一.Session 1.Session 介绍 我相信,搞Web开发的对Session一定再熟悉不过了,所以我就简单的介绍一下. Session:在计算机 ...

  5. 全栈工程师之路(二)—— JavaScript(网页前端脚本语言)

    javascript 是可以运行在网页前端的脚本语言,可以基于 html 之上实现更丰富的交互(网页内容的交互显示).异步回调.多线程.定时器.动画等. hello_world.html <ht ...

  6. 在IIS上部署.net core的webapi项目 以及502.5错误的两种解决方法

    首先要在服务器上面安装.net core https://github.com/dotnet/core/tree/master/release-notes/download-archives 这里面有 ...

  7. WPF公章制作之2

    原文:WPF公章制作之2 早前,我曾写过一篇:"在WPF中制作正圆形公章"(http://blog.csdn.net/johnsuna/archive/2007/10/12/182 ...

  8. A熟知SP.NET---WebForms UnobtrusiveValidationMode 必须“jquery”ScriptResourceMapping。

    我相信,有过ASP.NET人们学习经验RequiredFieldValidator控制(验证非空控制)一定不会陌生,禁止控制输入定义的内容的作用(该属性InitialValue的值.属性默认值为空字符 ...

  9. requireJS简单的学习门户网站

    总结 requireJS.这翻译成中国"必须js".说白了就是装js文件与.如何装好了?.这是继AMD标准化的模块化装.除了AMD另一种规范称为CMD规范.跟随CMD兼容模块加载. ...

  10. 使用WinPcap获取网卡MAC地址

    关键字:WinPcap 网卡 MAC地址 作者:txw1958 在WpdPack_4_1_2\WpdPack\Examples-remote\PacketDriver\GetMacAddress\目录 ...