Явно передав * это в C ++ - PullRequest
1 голос
/ 06 апреля 2020

Читая о *this, я увидел:

Когда для объекта вызывается нештатная c функция-член, компилятор передает адрес объекта в функция как скрытый аргумент.

Затем я попытался:

#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, тогда это должно сработать, не так ли?

Ответы [ 3 ]

3 голосов
/ 06 апреля 2020

Разрешено ли это делать только компиляторам?

Точно. Вот почему он называется скрытым: это то, что компилятор делает от вашего имени, но это скрыто от кода C ++, который его использует.

Компилятор должен каким-то образом передать указатель this на функцию-член, но ему не нужно рассказывать, как он это делает. Он может скомпилировать код, эквивалентный MyClass::getVar(&obj), передав указатель this так же, как он передал бы аргумент для C функции free(foo). Или он может использовать другой механизм, который полностью несовместим с передачей аргументов, не являющихся членами. То, что он делает под капотом, определяется стандартом Abstract Binary Interface (ABI) платформы, который не является частью стандарта языка C ++. То, что происходит в Windows, может значительно отличаться от того, что происходит в Linux, и Linux в ARM может отличаться от Linux в X86 и т. Д. c.

Тем не менее, вы можете взгляните на то, что на самом деле происходит, сказав компилятору создать код сборки. Для gcc значение заклинания будет

g++ -S -Os interestingCode.cpp

. В результате будет получен файл .s, который содержит, как g++ фактически перевел ваш код.

2 голосов
/ 06 апреля 2020

obj.getVar(&obj)

Эта версия не может быть скомпилирована, поскольку функция-член getVar() не объявлена ​​для каких-либо параметров.

MyClass::getVar(&obj)

Эта версия использует синтаксис для доступа к функции static, но getVar() не является static и не принимает никаких параметров.

Примечание: Вызов obj.getVar() работает, поскольку он задает какой экземпляр объекта использовать (т. е. часть obj.) для выполнения функции-члена и концептуально, как функция-член прошла указатель this .

1 голос
/ 06 апреля 2020

Когда вы делаете obj.getVar () , это уже явно указывает указатель * this = & obj и передает getVar. Это не скрыто. Это явно передается левой стороне функции. Вы можете использовать obj.getVar () или ptrObj-> getVar (), но в C ++ не разрешается использовать такую ​​конструкцию getVar (thisptr). Скрытое означает, что слово this нигде не объявлено, но вы можете использовать его внутри функции.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...