Это хороший вопрос. Если мы прочитаем §3.8, время жизни объекта с нетривиальным конструктором начинается только после завершения конструктора (завершена инициализация). А несколькими абзацами позже стандарт разграничивает, что мы можем и что не можем делать с указателем до того, как началось время жизни объекта, но после того, как память, которую будет занимать объект, будет выделена (и указатель this
в списке инициализации наверняка покажется вписаться в эту категорию, учитывая приведенное выше определение): в частности
Программа имеет неопределенное поведение, если:
[...]
- указатель неявно преобразуется в указатель на тип базового класса или
[...]
В вашем примере тип указателя в параметре базового класса имеет тип базового класса, поэтому указатель this
производного класса должен быть неявно преобразован в него. Что является неопределенным поведением в соответствии с вышеизложенным. Но... чтобы вызвать конструктор базового класса, компилятор должен неявно преобразовать адрес в указатель типа на базовый класс. Так что должны быть какие-то исключения.
На практике я ни разу не знал, чтобы компилятор в этом случае дал сбой, за исключением случаев, когда задействовано виртуальное наследование; Я определенно сталкивался с ошибками со следующим шаблоном:
class L;
class VB {};
class R : virtual VB { public: R( L* ); }
class L { L( char const* p ); };
class D : private virtual L, private virtual R { D(); }
D::D( char const* p ) : L( p ), R( this ) {}
Почему у компилятора были проблемы здесь, я не знаю. Он смог правильно преобразовать указатель, чтобы передать его как указатель this
конструктору L
, но не сделал этого правильно при передаче его в R
.
В этом случае обходной путь состоял в том, чтобы предоставить класс-оболочку для L с функцией-членом, которая возвращала указатель, например:
class LW : public L
{
public:
LW( char const* p ) : L( p ) {}
L* getAddress() { return this; }
};
D::D( char const* p ) : L( p ), R( this->getAddress(); ) {}
Результатом всего этого является то, что я не могу дать вам однозначный ответ, потому что не уверен, что имели в виду авторы стандарта. С другой стороны, я действительно видел случаи, когда это не срабатывало (и не так давно).
person
James Kanze
schedule
14.11.2011