Передача "this" в функцию из конструктора? - PullRequest
29 голосов
/ 15 января 2009

Могу ли я передать "this" в функцию в качестве указателя из конструктора класса и использовать его для указания на члены объекта до того, как конструктор вернет?

Безопасно ли это делать, если доступ к членам правильно инициализирован перед вызовом функции?

Как пример:

#include <iostream>

class Stuff
{
public:
    static void print_number(void *param)
    {
        std::cout << reinterpret_cast<Stuff*>(param)->number;
    }

    int number;

    Stuff(int number_)
        : number(number_)
    {
        print_number(this);
    }
};

void main() {
    Stuff stuff(12345);
}

Я думал, что это не сработает, но, похоже, так и есть. Это стандартное поведение или просто неопределенное поведение у меня на пути?

Ответы [ 4 ]

32 голосов
/ 15 января 2009

Когда вы создаете экземпляр объекта в C ++, код в конструкторе выполняется последним. Вся остальная инициализация, включая инициализацию суперкласса, выполнение конструктора суперкласса и выделение памяти, происходит заранее. Код в конструкторе на самом деле просто для выполнения дополнительной инициализации после создания объекта. Поэтому вполне допустимо использовать указатель «this» в конструкторе класса и предполагать, что он указывает на полностью построенный объект.

Конечно, вам все равно нужно остерегаться неинициализированных переменных-членов, если вы еще не инициализировали их в коде конструктора.

4 голосов
/ 15 января 2009

Хороший ответ на этот вопрос можно найти здесь (FAQ по C ++).

Все унаследованные члены и члены вызывающего класса гарантированно были созданы в начале выполнения кода конструктора, и поэтому в них можно безопасно ссылаться.

Основная проблема заключается в том, что вы не должны вызывать виртуальные функции на this. В большинстве случаев, когда я пытался это сделать, он просто вызывает функцию базового класса, но я полагаю, что стандарт говорит, что результат не определен.

0 голосов
/ 15 января 2009

В качестве дополнительного примечания к представленному коду, я бы вместо этого шаблонизировал void*:

class Stuff
{
public:
    template <typename T>
    static void print_number(const T& t)
    {
        std::cout << t.number;
    }

    int number;

    Stuff(int number_)
    : number(number_)
    {
        print_number(*this);
    }
};

Тогда вы получите ошибку компиляции, если тип t не имеет члена number.

0 голосов
/ 15 января 2009

Энди, я думаю, вы ошибаетесь в отношении неопределенной части стандарта.

Когда вы находитесь в конструкторе, «this» - это указатель на объект, типом которого является базовый класс создаваемого вами объекта, что означает, что виртуальные функции частично реализованы в базе. будет вызван класс, а указатели в виртуальной таблице не будут отслеживаться.

Больше информации в C ++ Faq Lite ...

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