【问题标题】:Explicitly passing *this in C++在 C++ 中显式传递 *this
【发布时间】:2020-04-06 13:55:38
【问题描述】:

在阅读*this 时,我看到:

当为对象调用非静态成员函数时,编译器 将对象的地址作为隐藏参数传递给函数。

然后我尝试了:

#include <iostream>

class MyClass
{
    int myVar;
public:
    MyClass(const int& val) : myVar{val} {}
    // int getVar(MyClass* this) <-- Error: expected ',' or '...' before 'this'
    int getVar()
    {
        return this->myVar;
    }
};

int main()
{
    MyClass obj(22);
    // std::cout << obj.getVar(&obj);      <-- Error: no matching function
    // std::cout << MyClass::getVar(&obj); <-- Error: no matching function
    std::cout << obj.getVar();
    return 0;
}

为什么我无法访问隐藏的参数?会不会因此而被称为“隐藏”?

是否只允许编译器这样做?我们不能在函数签名中明确提及*this吗?

在问这个问题之前我找到的最接近的答案是this。但是我尝试了这种方式,但仍然出现错误。我能得到这些错误信息的解释吗?因为,如果编译器实际上修改了这些函数签名以包含*this,那么这应该可以工作,不是吗?

【问题讨论】:

  • getVar() 不接受任何参数,因此这两个调用不起作用。从概念上讲,您已经通过使用 obj. 传递“this”,这是用于执行成员函数的实例。
  • 请包含完整的错误消息(和无效代码)
  • @idclev463035818 非工作代码是注释掉的行。如果我将它们全部取消注释,则错误消息会很长,并且会显示多字符常量等内容。lol
  • this 是一个关键字。你不能这样命名一个变量。但是您可以编写例如int getVar(MyClass* theOtherThis),它会起作用。您可以在getVar() 中访问thistheOtherThis,两者都相等。问题是:你为什么要做这样的事情?
  • @ArdentCoder 认为“隐藏参数”是一个实现细节。理论上,只要结果相同,编译器可以使用完全不同的技术。

标签: c++ class object this member-functions


【解决方案1】:

是否只有编译器可以这样做?

没错。这就是它被称为隐藏的原因:这是编译器代表您执行的操作,但对使用它的 C++ 代码是隐藏的。

编译器必须以某种方式将this 指针传递给成员函数,但它不需要告诉你它是如何做到的。它可以将代码编译为与MyClass::getVar(&amp;obj) 等效的代码,并以与传递C 函数free(foo) 的参数相同的方式传递this 指针。或者它可能使用与非成员参数传递完全不兼容的不同机制。它的底层功能由平台的抽象二进制接口标准 (ABI) 定义,它不是 C++ 语言标准的一部分。 Windows 下发生的情况可能与 Linux 下发生的情况大不相同,ARM 上的 Linux 可能与 X86 上的 Linux 不同,等等。

也就是说,您可以通过告诉编译器生成汇编代码来了解实际发生的情况。对于gcc,咒语是

g++ -S -Os interestingCode.cpp

这将生成一个.s 文件,其中包含g++ 实际翻译您的代码的方式。

【讨论】:

    【解决方案2】:

    obj.getVar(&amp;obj)

    此版本无法编译,因为getVar() 成员函数未声明带任何参数。

    MyClass::getVar(&amp;obj)

    此版本使用语法访问static 函数,但getVar() 不是static,也不接受任何参数。

    注意:obj.getVar() 调用有效,因为它指定使用哪个对象实例(即obj. 部分)来执行成员函数,并且在概念上是成员函数的方式通过了this 指针。

    【讨论】:

    • 但是编译器会自动放置*this... 那么,函数调用不匹配怎么会发生呢?如果这太天真了,我很抱歉。
    • @ArdentCoder 这是不匹配的,因为 you 没有提供具有该签名的函数,因此该函数不存在。
    • 是的,我知道,但我认为编译器正在为我生成该函数签名:P
    【解决方案3】:

    当您执行 obj.getVar() 时,它已经明确指定了指针 *this=&obj 并隐式传递给 getVar。它没有隐藏。它在函数的左侧显式传递。您可以使用 obj.getVar() 或 ptrObj->getVar() 但在 C++ 中不允许使用这种构造 getVar(thisptr)。隐藏意味着名为 this 的变量没有声明,但您可以在函数内部使用。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-10-08
      • 1970-01-01
      • 2014-04-24
      • 1970-01-01
      • 2016-03-29
      • 1970-01-01
      • 1970-01-01
      • 2014-06-26
      相关资源
      最近更新 更多