【问题标题】:C++ this pointer, hidden argument in function callsC++ this 指针,函数调用中的隐藏参数
【发布时间】: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);通过宏替换

【问题讨论】:

    标签: c++ this


    【解决方案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 中提供了对象系统。我猜它大量使用了宏。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2013-03-31
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2013-04-17
          • 1970-01-01
          相关资源
          最近更新 更多