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

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

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. kindeditor 4 上传下载文件

    jsp代码 1 <script type="text/javascript" src="${pageContext.request.contextPath}/kin ...

  2. window.url.createobjecturl 兼容多种浏览器(IE,google,360,Safari,firefox)

    <script type="text/javascript"> function setImagePreview() { var docObj = document.g ...

  3. Linux虚拟文件系统(VFS)学习

    虚拟文件系统(Virtual Filesystem)也可称之为虚拟文件系统转换(Virtual Filesystem Switch),是一个内核软件层,用来处理与Unix标准文件系统相关的全部系统调用 ...

  4. How to configure spring boot through annotations in order to have something similar to <jsp-config> in web.xml?

    JSP file not rendering in Spring Boot web application You will need not one but two dependencies (ja ...

  5. SQL SERVER配置[转]

    感谢shuhao,sql server的配置都是他教的,下面是他写的总结,方便自己以后使用 总结一下,感觉比较实用.------------------------------------------ ...

  6. node lesson3

    var express = require('express'); var superagent = require('superagent'); var cheerio = require('che ...

  7. 关于ExpandableListView的一个小例子

    喜欢显示好友QQ那样的列表,可以展开,可以收起,在android中,以往用的比较多的是listview,虽然可以实现列表的展示,但在某些情况下,我们还是希望用到可以分组并实现收缩的列表,那就要用到an ...

  8. 至HDFS附加内容

    在最近的项目开发中遇到的问题: 需要产生良好hdfs文件的其他内容.但使用在线版1.0.3.见发现官方文件,于1.0.4支持的文件的版本号之后append 一下是向hdfs中追加信息的操作方法 假设你 ...

  9. Asp.net固定功能位充满了零(解决,演示样本)!

    Asp.net固定功能位充满了零(解决.演示样本)! 在发展,其中,数实现出现8数字.但是,需要使用0加厚.例如:123,代表:0000123. 真实的比例,如下: decimal aaa = 123 ...

  10. [Hibernate系列—] 3. 映射文件和使用SchemaExport制作自己主动Schema

    自己定义映射文件 这里的映射文件指的是相应到数据库表的xml 的定义文件. 相应的每一个数据库表栏位, 能够定义的属性有: 属性名 类型 Description length number 栏位的长度 ...