[翻译]C++教程:指向成员函数的指针

成员函数指针与高性能的C++委托(上篇) 成员函数指针与高性能的C++委托(上篇) Member Function Pointers and the Fastest Possible C++ Delegates 撰文:Don Clugston 翻译:周翔 引子 标准C++中没有真正的面向对象的函数指针。这一点对C++来说是不幸的,因为面向对象的指针(也叫做“闭包(closure)”或“委托(delegate)”)在一些语言中已经 阅读详情

转自:http://kelvinh.github.io/blog/2014/04/19/research-on-operator-new-and-delete/

这是一篇翻译的文章,原文详细解释了C++中指向成员函数的指针,因为带有“教程”一词,所以比较通俗易懂。为了使文章读起来通俗有趣,翻译君并未一字一句一板一眼地翻译,并大量使用了诙谐的词汇(如“码农”)。另外,原文的某些地方分段不太合适(小学语文可能是体育老师教的。。),有些地方也稍嫌啰嗦,所以翻译君自己作了一些调整。如果对翻译君的翻译质量有意见,建议前往 原地址 围观。

咦?还不走?那废话少说,我们开始了啊。


关于成员函数指针

成员函数指针是C++最少用到的语法之一,甚至有经验的C++码农有时候也会被它搞晕。这是一篇针对于初学者的教程,同时也给有经验的码农分享了一些我个人对底层机制的挖掘。在开始之前,让我们先看一段在第一次看时一定会高呼“我++”的代码(说明,这些代码都是翻译君重新手敲的,改正了原文代码中的一些不太好的空格、缩进,下同):

//mem_fun1.cpp
#include <iostream>

class Foo {
public:
    Foo(int i = 0) { _i = i; }
    void f() {
        std::cout << "Foo::f()" << std::endl;
    }
private:
    int _i;
};

int main() {
    Foo *p = 0;
    p->f();
}

// Output:
// Foo::f()

为什么我们能通过一个空指针调用成员函数?看起来好像编译器根本不鸟p的值是什么,只介意p的类型。别着急,咱先吊吊胃口,把答案留到后面的章节。现在,我们所能知道的是,编译器准确地知道要调用哪个函数。这就是所谓的“静态绑定”。因为成员函数可以静态绑定(并不是总能静态绑定,待会儿讨论),所以它们的地址是在编译阶段决定的(同样并不是永远如此)。直观地讲,应该有一种方法可以保存成员函数的地址。而且,真有这么一种方法,那就是——成员函数指针。

C++语法

下面的语法展示了如何声明一个成员函数指针:

Return_Type (Class_Name::* pointer_name) (Argument_List);

Return_Type:   member function return type.
Class_name:    name of the class in which the member function is declared.
Argument_List: member function argument list.
pointer_name:  a name we'd like to call the pointer variable.

例如,我们定义一个类 Foo 和一个成员函数 f :

int Foo::f(string);

我们可以给这个成员函数指针起一个“高大上”的名字 fptr ,所以我们就有了下面的内容:

Return_Type:   int
Class_Name:    Foo
Argument_List: string

declaration of a  pointer-to-member function named "fptr":
  int (Foo::*fptr) (string);

现在,指定一个成员函数给我们“高大上”的 fptr :

fptr = &Foo::f;

当然,就连脑残都知道可以将声明和初始化结合起来:

int (Foo::*fptr) (string) = &Foo::f;

为了通过函数指针来调用成员函数,我们使用成员指针选择操作符(翻译君表示也不知道该怎么翻译,原文是pointer-to-member selection operators), .* 或者 ->*。下面的代码演示了基本用法:

#include <iostream>
#include <string>

using namespace std;

class Foo {
public:
    int f(string str) {
        cout << "Foo::f()" << endl;
        return 1;
    }
};

int main(int argc, char *argv[]) {
    int (Foo::*fptr) (string) = &Foo::f;
    Foo obj;
    (obj.*fptr)("str"); // 通过对象来调用 Foo::f()
    Foo *p = &obj;
    (p->*fptr)("str"); // 通过指针来调用 Foo::f()
}

注意: .*fptr 绑定fptr到对象obj,而 ->*fptr 则绑定fptr到指针p所指向的对象。(还有一个 重要的区别 是:我们可以重载后者,却不能重载前者)。在 (obj.*fptr) 和 (p->*fptr) 两边的括号是语法所强制要求的。

成员函数指针不是常规指针

成员函数指针不像常规指针那样保存某个“准确”的地址。我们可以把它想像成保存的是成员函数在类布局中的“相对”地址。让我们来展示一下二者的不同。我们只对类 Foo做一个小手术:将成员函数 f 变成 static :

#include <iostream>
#include <string>

using namespace std;

class Foo {
public:
    static int f(string str) {
        cout << "Foo::f()" << endl;
        return 1;
    }
};

int main(int argc, char *argv[]) {
    // int (Foo::*fptr) (string) = &Foo::f; // 错误
    int (*fptr) (string) = &Foo::f; // 正确
    (*fptr)("str"); // 调用 Foo::f()
}

一个静态成员函数没有 this 指针。除了它和其它的类成员共享命名空间Foo(在我们的例子中命名空间是 Foo:: )之外,它和常规全局函数是一样的。所以,静态成员函数不是类的一部分,成员函数指针的语法对常规函数指针并不成立,例如上面例子中的静态成员函数指针。

int (Foo::*fptr) (string) = &Foo::f;

上面这行代码在g++ 4.2.4中编译的错误信息为:“不能将 int (*)(std::string)转化成 int (Foo::*)(std::string) ”。这个例子证明了成员函数指针不是常规指针。另外,为什么C++如此费心地去发明这样的语法?很简单,因为它和常规指针是不同的东西,而且这样的类型转换也是违反直觉的。

C++类型转换规则

非虚函数情形

我们在前面一节看到,成员函数指针并不是常规指针,所以,成员函数指针(非静态)不能被转换成常规指针(当然,如果哪个脑残真想这么做的话,可以使用汇编技术来暴力解决),因为成员函数指针代表了 偏移量 而不是 绝对地址 。但是,如果是成员函数指针之间相互转换呢?

//memfunc4.cpp
#include <iostream>

class Foo {
public:
    int f(char *c = 0) {
        std::cout << "Foo::f()" << std::endl;
        return 1;
    }
};

class Bar {
public:
    void b(int i = 0) {
        std::cout << "Bar::b()" << std::endl;
    }
};

class FooDerived : public Foo {
public:
    int f(char *c = 0) {
        std::cout << "FooDerived::f()" << std::endl;
        return 1;
    }
};

int main(int argc, char *argv[]) {
    typedef int (Foo::*FPTR) (char*);
    typedef void (Bar::*BPTR) (int);
    typedef int (FooDerived::*FDPTR) (char*);

    FPTR fptr = &Foo::f;
    BPTR bptr = &Bar::b;
    FDPTR fdptr = &FooDerived::f;

    // bptr = static_cast<void(Bar::*)(int)>(fptr); // 错误
    fdptr = static_cast<int(Foo::*)(char*)>(fptr); // 正确,逆变性规则

    Bar obj;
    ( obj.*(BPTR) fptr )(1); // 调用 Foo::f()
}

// Output:
// Foo::f()

在上面的代码中,我们首先使用了我们的老朋友 typedef 。它让这些繁琐的定义变得清晰起来。关键是,fptr是什么类型?它的类型是:

int (Foo::*) (char*);

或者等价地说——FPTR。如果我们仔细看上面的代码:

bptr = static_cast<void(Bar::*)(int)>(fptr);

这一行会出错,因为 不同的非静态非虚成员函数具有强类型因此不能相互转化 ,但是:

fdptr = static_cast<int(Foo::*)(char*)>(fptr);

这一行却是正确的!我们可以将一个指向派生类的指针赋值给一个指向其基类的指针(即"is-a"关系),而所谓的“逆变性规则”(翻译君:不知道是啥,原文是contravariance rule)正是这种规则的反面。这个规则提供了将 FooDerived::* 应用到任何 Foo::* 能被应用的地方的基本保证。在代码最后两行:

Bar obj;
( obj.*(BPTR) fptr)(1);

尽管我们想要调用的是 Bar::b() ,但是 Foo::f() 却被调用了,因为fptr是静态绑定(翻译君注:这里的静态绑定,即指在编译阶段,fptr的值已经确定了,所以即使进行强制转换,依然调用的是Foo类的f()函数)。(请围观成员函数调用和 this 指针)

虚函数情形

我们只将前例中的所有成员函数变成虚函数,其它都不动:

#include <iostream>

class Foo {
public:
    virtual int f(char *c = 0) {
        std::cout << "Foo::f()" << std::endl;
        return 1;
    }
};

class Bar {
public:
    virtual void b(int i = 0) {
        std::cout << "Bar::b()" << std::endl;
    }
};

class FooDerived : public Foo {
public:
    int f(char *c = 0) {
        std::cout << "FooDerived::f()" << std::endl;
        return 1;
    }
};

int main(int argc, char *argv[]) {
    typedef int (Foo::*FPTR) (char*);
    typedef void (Bar::*BPTR) (int);

    FPTR fptr = &Foo::f;
    BPTR bptr = &Bar::b;

    FooDerived objDer;
    (objDer.*fptr)(0); // 调用 FooDerived::f(),而不是 Foo::f()

    Bar obj;
    ( obj.*(BPTR) fptr )(1);// 调用 Bar::b(),而不是 Foo::f()
}

// Output:
// FooDerived::f()
// Bar::b()

如我们所看到的,当成员函数是虚函数的时候,成员函数能够具有多态性并且现在调用的是 FooDerived::f() ,而且 Bar::b() 也能被正确调用了。因为 “一个指向虚成员的指针能在不同地址空间之间传递,只要二者使用的对象布局一样” (此话来自C++老爸 Bjarne Stroustrup 的 《C++程序设计语言》 )。当函数是虚函数的时候,编译器会生成虚函数表,来保存虚函数的地址。这是和非虚函数之间的最大不同,因此,运行时的行为也是不同的。

成员函数指针数组及其应用

成员函数指针的一个重要应用就是根据输入来生成响应事件,下面的 Printer 类和指针数组 pfm 展示了这一点:

#include <stdio.h>
#include <string>
#include <iostream>

class Printer { // 一台虚拟的打印机
public:
    void Copy(char *buff, const char *source) { // 复制文件
        strcpy(buff, source);
    }

    void Append(char *buff, const char *source) { // 追加文件
        strcat(buff, source);
    }
};

enum OPTIONS { COPY, APPEND }; // 菜单中两个可供选择的命令

typedef void(Printer::*PTR) (char*, const char*); // 成员函数指针

void working(OPTIONS option, Printer *machine,
             char *buff, const char *infostr) {
    PTR pmf[2] = { &Printer::Copy, &Printer::Append }; // 指针数组

    switch (option) {
    case COPY:
        (machine->*pmf[COPY])(buff, infostr);
        break;
    case APPEND:
        (machine->*pmf[APPEND])(buff, infostr);
        break;
    }
}

int main() {
    OPTIONS option;
    Printer machine;
    char buff[40];

    working(COPY, &machine, buff, "Strings ");
    working(APPEND, &machine, buff, "are concatenated!");

    std::cout << buff << std::endl;
}

// Output:
// Strings are concatenated!

在上述代码中, working 是一个用来执行打印工作的函数,它需要几个参数:1. 菜单选项;2. 可用的打印机;3. 字符串目的地;4. 字符串来源。上述代码中字符串来源是两个字符串常量"Strings "和"concatenated!",而成员函数指针数组被用来根据菜单选项执行相应的打印动作。

成员函数指针另外一个重要的应用可以在STL的 mem_fun() 中找到。(翻译君去看了一下 mem_fun() 的源代码,原来是用成员函数来构造仿函数functor的。)

成员函数调用和 this 指针

现在我们回到文章最开始的地方。为什么一个空指针也能调用成员函数?对于一个非虚函数调用,例如: p->f() ,编译器会生成类似如下代码:

Foo *const this = p;
void Foo::f(Foo *const this) {
    std::cout << "Foo::f()" << std::endl;
}

所以,不管p的值是神马,函数 Foo::f 都可以被调用,就像一个全局函数一样!p被作为 this 指针并当作参数传递给了函数。而在我们的例子中 this 指针并没有被解引用,所以,编译器放了我们一马(翻译君表示,这其实跟编译器没有关系,即使我们在成员函数中使用this指针,编译照样能通过,只不过在运行时会crash)。假如我们想知道成员变量 _i 的值呢?那么编译器就需要解引用 this 指针,这只有一个结果,那就是我们的好兄弟——未定义行为(undefined behavior)。对于一个虚函数调用,我们需要虚函数表来查找正确的函数,然后, this 指针被传递给这个函数。

这就是非虚函数、虚函数、静态函数的成员函数指针使用不用实现方式的根本原因。

结论

简单总结一下,通过上述文章,我们学到了:

  1. 成员函数指针声明和定义的语法
  2. 使用成员指针选择操作符来调用成员函数的语法
  3. 使用 typedef 写出更加清晰的代码
  4. 非虚成员函数、虚函数、静态成员函数之间的区别
  5. 成员函数指针和常规指针的对比
  6. 不同情形下的成员函数指针转换规则
  7. 如何使用成员函数指针数组来解决特定的设计问题
  8. 编译器是如何解释成员函数调用的

我衷心希望这篇教程能打开通往上述要点的相关高级技巧的大门,例如多重继承、虚继承下的成员函数指针,以及编译器的相关实现,例如“巨硬”家的Thunk技术(原文这里有链接,但翻译君去看了一下,不仅又老又旧(还在讲Windows 98和16位程序),而且只是巨硬的support性质的文章,所以就不贴链接了,免得浪费各位看官宝贵的青春:-p)。

那么,就到这里了,谢谢各位的围观,希望能对各位有所帮助。(翻译君表示,这哥们怎么这么啰嗦,和天朝棺猿有得一拼:-p)

TCP/IP工业通信C#极致实现:工业级TcpClient封装 + 粘包拆包彻底解决 + 高频采集专项优化(完整可投产) 在工业自动化、PLC通信、工业传感器/模块、产线高频数据采集等场景中,TCP/IP是绝对主流的通信方式,相比串口/485,具备传输速率高、距离无限制、布线简单、抗干扰强的优势。但工业TCP通信和普通桌面TCP通信有本质区别,工业场景的核心要求是:✔高可靠:7×24小时不间断运行,断网自动重连、异常自动恢复,绝不崩溃;✔无数据错误:彻底解决「粘包、拆包、半包」问题(工业通信第一大坑,90%的通信异常源于此);✔高频采集优化:支持级别的高频读写PLC/设备,无卡顿、无丢帧、CPU占用极低;✔。 阅读详情

相关推荐

省三医院新门诊大楼网络安全建设项目实施方案

为了响应国家建设数字医疗,构建医联网、医共体的号召,新门诊大楼现有计算机网络,实现各门诊室、药房、医学影像科室及后勤科室的终端数据互通。在互联网出口以三层模式部署两台防火墙,作为连接公网的出口设备;出于等保合规和自身业务安全的考虑,现需要该网络上通过网络安全设备实现安全建设。公网出口防火墙,配置攻击防御策略,防御互联网上的病毒进入内网。公网出口防火墙配置攻击防御策略,防御外网对内网的入侵行为。服务器取得边界防火墙,配置攻击防御策略,入侵防御策略。公网出口防火墙配置入侵防御策略,防御外网对内网发起的D。

m0_63645854的博客 2014

C++成员函数指针的应用

        C++中,成员指针是最为复杂的语法结构。但在事件驱动和多线程应用中被广泛用于调用回叫函数。在多线程应用中,每个线程都通过指向成员函数的指针来调用该函数。在这样的应用中,如果不用成员指针,编程是非常困难的。   刚遇到这种语法时也许会让你止步不前。但你会发现,使用恰当的类型定义之后,复杂的语法是可以简化的。本文引导你了解成员函数指针的声明,赋值和调用回叫函数。   成员函数指针的声明

搜索如风 3702

20220601超简单百度地图街景图片爬取+绿视率计算

真的不难咯。

weixin_39676904的博客 1万+

指向成员函数的函数指针

C语言中的函数指针还是很简单的,这里还是稍微总结一下: 函数地址: 函数名,&函数名,两者均可。 函数指针变量的定义方法: 把函数名替换为你喜欢的变量名,并在前面加*号,并把*号和函数名()起来。 函数指针类型的定义方法: 把上一步的变量名替换为你喜欢的类型名,前面再直接加typedef即可。 例子: (1) 函数定义如下: char *parseF...

野生猿-群号1025127672 1261

SPI模式下的SD卡读写,为什么你的数据总出错?详解时序与状态机避坑指南

本文深入探讨SPI模式下SD卡读写数据出错的根本原因,提供时序优化与状态机设计的实战指南。针对时钟周期计数、状态机跳转和忙检测等核心问题,详解命令时序细节、状态机同步策略及高级避坑技巧,帮助开发者提升SD卡在SPI模式下的稳定性和性能。

weixin_30514745的博客 263

上海市大数据中心笔试模拟试卷

为帮助考生熟悉上海市大数据中心笔试的题型、考点及答题逻辑,以下整理了一份的模拟试卷,涵盖大数据专业知识、行政职业能力测试(行测)、公共基础知识(含上海本地政策)三大核心模块,并附详细答案解析。

一叶之秋的博客 1815

指向成员函数的指针和this指针

1.指向类的成员函数的指针 (1)定义的一般形式:数据类型 (类名:: * 指针变量名)(参数表列) (2)使成员函数指针指向类的共用成员函数的一般形式:函数指针名=&类名::函数名 (3)利用函数指针调用类的成员函数一般形式:(对象名 . 函数指针名)() #include using namespace std; class Time { public: Time(int h, in...

weixin_43597743的博客 2810

Winget安装失败:深入解析InternetOpenUrl()错误0x80072efd的根源与修复

本文深入解析了使用Winget时遇到的InternetOpenUrl()错误0x80072efd。该错误通常源于DNS解析失败、网络代理配置不当或系统安全策略冲突,导致无法连接软件源。文章提供了从刷新DNS、修改Hosts文件到配置代理等一套完整的诊断与修复方案,帮助开发者快速解决安装障碍,恢复Winget的正常使用。

weixin_29290259的博客 934

C++指向类成员的函数指针

定义:类成员函数指针(member function pointer),是 C++ 语言的一类指针数据类型,用于存储一个指定类具有给定的形参列表与返回值类型的成员函数的访问信息。基本上要注意的有两点:1、函数指针赋值要使用 & 2、使用 .* (实例对象)或者 ->*(实例对象指针)调用类成员函数指针所指向的函数 下面看两个例子:对于 nonstatic member function (非静态成员函数)取地址,获得该函数在内存中的实际地址对于 virtual function(虚函数), 其地址在编译时期

weixin_43488671的博客 3892

[Dify] -进阶13- 使用“知识库 + 工作流”打造智能推荐系统

本文介绍了在Dify平台上构建智能推荐系统的方法,重点阐述了知识库与工作流技术的结合应用。通过知识库管理RAG流程,实现文档上传、向量嵌入和检索优化;利用工作流设计节点化推荐逻辑,支持并行处理与条件分支。以电话销售话术推荐为例,展示了从数据收集到实时生成的完整流程。该方法具有准确性高、扩展性强、维护简便等优势,可广泛应用于各类推荐场景,实现从数据存储到智能推荐的闭环解决方案。

技术小甜甜:传播可落地技术,帮助个人和企业降低解决真实场景问题的成本 1068

YOLOv10改进策略【Neck】| arXiv 2025 分层多头注意力HMHA 子空间拆分提多样 + 通道重排降冗余,强化目标检测精度

HMHA(Hierarchical Multi-Head Attention,分层多头注意力)旨在解决传统多头注意力(MHA)在图像恢复任务中的核心缺陷——特征冗余。传统MHA将通道均匀拆分给各个头,导致不同头学习的子空间信息相似,进而出现多头关注同一区域、忽略退化区域修复的问题,限制了模型的特征表达能力。HMHA通过“分层子空间拆分+通道重排序”策略,让每个头学习差异化、互补的上下文特征,从根源上缓解冗余,提升图像恢复任务中对复杂退化场景的特征捕捉能力。

Limiiiing的博客 105

大胆使用指向成员函数的指针

大胆使用指向成员函数的指针         指向成员函数的指针是C++中比较复杂的语法结构,然而,它却是事件驱动和多线程环境中不可缺少的,特别是当从外部调用成员函数的时候。在多线程里,每一个线程都通过指向成员函数的指针调用这一函数。如果C++没有这些语法特性,那么在很多情况下进行C++程序开发会遇到很多麻烦。        也许你开始会被这一性质的语法吓倒,但当你熟悉之后你就会觉得它相当方便,

Zaobird的专栏 4880

【PINN物理信息网络】基于PINN物理信息网络求解瞬态薛定谔方程(python)

【PINN物理信息网络】基于PINN物理信息网络求解瞬态薛定谔方程(python)

k8291121的博客 2724

C++教程:指向成员函数的指针

转载自:https://kelvinh.github.io/blog/2014/03/27/cpp-tutorial-pointer-to-member-function/ Kelvin的胡言乱语 ==============> 重剑无锋,大巧不工。 Blog Wiki Tags About GitHub RSS [翻译]C++教程:指向成员函数的指针 这

jerry_csdn_zhou的博客 783

Statistics and Machine Learning Toolbox

Statistics and Machine Learning Toolbox(带书签),MATLAB统计学习工具

NTscan扫描工具

ntscan是一个扫描器,可以扫描没有密码和弱密码的共享,先到配置文件中填写猜测的用户名和密码,扫描过程中右侧出现的是扫描日志。

C++ this指针的理解和作用

01 C++ 程序到 C 程序的翻译 要想理解 C++ 的 this 指针,我们先把下面的 C++ 代码转换成 C 的代码 class Car { public: int m_price; // 成员变量 void SetPrice(int p) // 成员函数 { m_price = p; } }; int main() { Car car; car....

小林coding 2222

汉书HE8,好用的汇编代码编写工具

汉书HE8,好用的汇编代码编写工具早期编写汇编代码所用功能强大

【C++基础】Day 8:函数指针 VS 指针函数 | 指针常量 VS 指向常量的指针

本文系统梳理了C++中两类易混淆指针概念:1)函数指针与指针函数:前者是指向函数的指针变量,用于回调、函数表等;后者是返回指针的函数。区分关键看标识符最近的符号是*还是()。2)指针常量与指向常量的指针:前者指针不可改但内容可改,后者内容不可改但指针可改,const位置决定限制对象。文章通过定义解释、图表对比、代码示例和面试题分析,帮助读者清晰区分这些高频考点概念,掌握指针声明的阅读技巧和使用场景。

冰冻三尺非一日之寒 1613

温度PID控制PLC程序

温度PID稳定控制程序,适用于欧姆龙PLC,对其他PLC也具有很大参考价值

C++指针详解-史上最全

C++指针详解-史上最全pointer定义array 与 pointerpointer 初始化pointer 的计算pointer 与 conststring和pointerpointer 指向 pointervoid pointer(泛型指针)非法指针和空指针pointer 和 function 写在前面:这我第一次写blog,同时也是为了即将到来的C++面试进行复习。以后会不定期更新我的复习笔...

Jason_Chen93的博客 6021

当C++指向对象的指针被赋值为NULL,对象那些函数可以运行?

当C++指向对象的指针被赋值为NULL,对象那些函数可以运行? ——源自一道笔试选择题: 当程序如下时可以运行 [cpp] view plaincopy "font-size:24px;">// 3fun.cpp : Defines the entry point for the console application. 

Mars 尘的专栏 2705

C++程序翻译成C语言程序

C++程序翻译成C语言程序 C++语言是在C语言的基础上发展过来的,第一个C++的编译器实际上是将C++程序翻译成C原因程序,再通过C语言编译器进行编译。 然而C语言中没有类的概念,只有结构,而且函数还是全局函数,没有类成员函数。在翻译时,将class翻译为struct、对象翻译成结构变量,但是对类的成员函数应该如何翻译,对MyCar.Modify();这样通过一个对象调用成员函数的语句,又该...

King逍灬遥 4366

【C/C++】指针常量、常量指针、指向常量的常指针

而第二组的翻译和第一组的翻译在常量指针的位置刚好出现了两种截然不同的结果,或许这就是很多人在网上搜文章时感觉都不是很统一的原因吧,一部分文章按照第一组翻译去解释意思,另一部分文章按照第二组去解释就会导致看下来更加的晕头转向了。从英语可以很快速的理解这几个术语的含义,但是由于翻译的问题,就导致大家在初学 C++ 时会很晕头转向,被这几个概念搞的摸不清头脑。防止读者产生误会,我会在后续使用英语名来代替中文名,另外读者不用过分纠结中文名字,只需要能够分辨清楚。的定义方法与用法即可。

FuckerGod的博客 2313

C++程序到C程序的翻译—— this指针

C++程序到C程序的翻译 C 语言没有类的概念,只有结构,函数都是全局函数,没有成员函数。翻译时,将class翻译为struct、对象翻译为结构变量、成员函数只能被翻译成全局函数。对于"myCar.Modify();"这样的语句,也只能被翻译成普通的调用全局函数的语句。那如何让翻译后Modify全局函数还能作用在myCar这个结构变量上呢?C++通过引入"this"指针来实现。 一段C++程序到C程序的翻译: C++程序: class CCar { public: int price; void S

ltimaginea的博客 413

成员函数指针与高性能的C++委托(下篇)

成员函数指针与高性能的C++委托(下篇) Member Function Pointers and the Fastest Possible C++ Delegates 撰文:Don Clugston 翻译:周翔 (接中篇) 委托(delegate) 和成员函数指针不同,你不难发现委托的用处。最重要的,使用委托可以很容易地实现一个Subject/Observer设计模式的改进版[GoF,

8932

C++ this指针深度解析

一、C++ 程序到C程序的翻译 C++ 是在C语言的基础上发展而来的,第一个 C++ 的编译器实际上是将 C++ 程序翻译成C语言程序,然后再用C语言编译器进行编译。C语言没有类的概念,只有结构,函数都是全局函数,没有成员函数。翻译时,将 class 翻译成 struct、对象翻译成结构变量是显而易见的,但是对类的成员函数应该如何翻译?对myCar.Modify();这样通过一个对象调用成员函数...

love、reading的博客 703

c++指向成员的指针(二)

上一篇文章我们讲解了成员指针的概念及用法,这里我们再深入来探讨一下。 我们知道一般的指针在32位平台上占4个字节,64位平台上占8个字节,但成员指针因为其特殊性,它不是一般的指针,在32位平台上它占8个字节,而在64位平台上占16个字节,这个我们可以通过sizeof很容易测得。 我这里的平台是64位,所以接下来以64位平台来研究一下,为何成员指针占16个字节呢?这个在标准中没有多少说明,但在

hmalloc的专栏 969

【C++】const修饰的成员函数

在日常学习中总是碰到const修饰的成员函数,自己也总是稀里糊涂的,只能是靠着编译器来区分const和非const成员函数的相互调用关系,今天在这里总结以下。 一.const修饰成员函数的格式 在成员函数的后边加上const void display() const { swap(5); cout &lt;&lt; "display()" &lt;&lt; endl;...

alidada_blog的博客 3628

成员函数指针与高性能的C++委托

Member Function Pointers and the Fastest Possible C++ Delegates  成员函数指针与高性能的C++委托 撰文:Don Clugston 翻译:周翔   引子 标准C++中没有真正的面向对象的函数指针。这一点对C++来说是不幸的,因为面向对象的指针(也叫做“闭包(closure)”或“委托(delegat

softfox的专栏 1168
上一篇: C/C++数据对齐
下一篇: 最受欢迎的C++代码段
飞鸟Mu
博客等级 码龄17年 16粉丝 75原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值