C++ this 指针,函数调用中的隐藏参数

Posted

技术标签:

【中文标题】C++ this 指针,函数调用中的隐藏参数【英文标题】:C++ this pointer, hidden argument in function calls 【发布时间】:2013-03-10 12:34:44 【问题描述】:

我有一个包含成员的堆栈类和一个名为 push 的函数。

class STACK

    int data;
    public:
    void push(int x)
    
        data=x;
    

C++ 做了什么来转换这个语句:

s1.push(3);

s1.push(this,3);

基本上我的问题是,在生成 this 指针并将其作为隐藏参数传递时会发生什么?

我实际上是在用 C 编写代码。我的目标是拥有一个尽可能接近 OOP 的程序。为此,我将函数指针作为结构的成员。因此,我想知道是否有可能以某种方式跟踪调用函数的结构(如“this”指针)。我不想做类似的事情: s1.push(&s1,3);因为它超出了我的目的。

是否可以转换 s1.push(3);到 s1.push(&1,3);通过宏替换

【问题讨论】:

【参考方案1】:

首先要做的事!声明:

s1.push(3);

未翻译为:

 s1.push(this, 3);

但是对于这样的事情:

STACK::push(&s1, 3); 

其中STACK::push 可以被视为类/命名空间STACK 下的全局/命名空间或静态函数,其原型为:

push(STACK const* pThis, int arg);

this 指针始终是方法(函数)的第一个参数。如果方法的参数为零,它仍然有一个参数(类的this 指针)。

【讨论】:

是否可以通过编码来实现? (我的意思是显式转换为 push(STACK const* pThis, int arg); ) 显而易见的问题是为什么。你为什么要这样做?也许你可以编写一个全局或静态函数并传递类的指针。 我实际上是在用 C 编码。我的目标是拥有一个尽可能接近 OOP 的程序。为此,我将函数指针作为结构的成员。因此,我想知道是否有可能以某种方式跟踪调用函数的结构(如“this”指针)。我不想做类似的事情: s1.push(&s1,3);因为它超出了我的目的。 好吧,你倒霉了。 C 没有很好的面向对象编程的设施。您需要显式传递您的函数应该处理的对象的地址。 是否可以转换 s1.push(3);到 s1.push(&1,3);通过宏替换【参考方案2】:

没有魔法

s1.push(3);

只是语法

STACK::push(&s1, 3);

【讨论】:

嗯,这里的“魔力”是 push(...) 变成了一个普通的(即 C 类型)函数,带有一个额外的 STACK* 参数。为了避免名称与其他普通函数发生冲突,在内部名称被“修改”以包括类名以及其他内容。 ...当方法变为虚拟时,事情会变得有点复杂;) 问题是关于 this 的魔力,这并没有什么魔力,它只是使用的对象的地址。我确实知道让 STACK::push 做正确的事情的magic 是否可以转换 s1.push(3);到 s1.push(&1,3);通过宏替换 我不确定我理解你所说的宏替换是什么意思,但在有限的意义上你可以做一些类似的事情。见C with Pseudo-Classes。【参考方案3】:
this = &s1

s1的地址是已知的,所以可以传递给STACK::push。就这么简单:)

【讨论】:

我完全同意。但代码行是 s1.push(3);怎么变成s1.push(this,3); 伙计,编译器不是 hello world 程序。 “但代码行是 s1.push(3)”不是一个论点。编译器完成的任务比传递隐藏参数要困难得多。 @DarshanShah:就像代码int main() 在你的文件系统中变成一个可执行文件一样:因为那是编译器所做的【参考方案4】:

C++ 不能完全转换语句(因为 C++ 是一种语言规范,您可以通过多种方式实现该语言,即使是 - 不道德地 - 有一群奴隶在纸上工作;您不需要计算机,即使你想要一个,拥有 C++)。编译器(例如 GCC)将语句转换为其他一些较低级别的表示。使用 GCC,它是 Gimple 语句,并且可以检查 Gimple 表示,例如带有MELT's probe 或-fdump-tree-gimple 和其他选项(如-fdump-tree-all-fdump-tree-ssa 等...)

【讨论】:

【参考方案5】:

不幸的是,您必须在 C 中显式或隐式指定指针。

对于 C++,编译器负责将隐式 this 指针设置为类成员函数的参数。在你的代码中,成员函数在编译时被编译器自动修改为void STACK::push(STACK*, int),然后,当调用成员函数STACK::push时,编译器会将对象地址(this)设置为参数(一般是第一个)到成员函数STACK::push

没有C编译器会提供上述功能,因此,设置指针是用户的责任。

【讨论】:

【参考方案6】:

在您编辑之后,问题又涉及另一个问题 - C 语言中的 OOP。这很困难且类型不安全,但可以实现。你可以看看 GObject 库,它在 C 中提供了对象系统。我猜它大量使用了宏。

【讨论】:

以上是关于C++ this 指针,函数调用中的隐藏参数的主要内容,如果未能解决你的问题,请参考以下文章

2隐形的指针

Review cpp day05

c++和c#中'this'指针的概念和数据类型

C++ this详解

C++ CreateThread函数如何传递this指针作为参数

C++学习(四五零)重载覆盖隐藏