The base-class constructors and class member constructors are called before this constructor. In effect, you've passed a pointer to an unconstructed object to another constructor. If those other constructors access any members or call member functions on this, the result will be undefined. You should not use the this pointer until all construction has completed.
Звучит это довольно странно, поскольку , согласно стандарту, сконструированным объект может считаться только после завершения работы конструктора (конструкторов всех уровней иерархии начледования). С этой точки зрения использование this в теле конструктора ни чем не лучше, чем в списке инициализации. Однако при использовании this в теле конструктора данное предупреждение не возникает. В целом, предупреждение достаточно бесполезное.
--
Не можешь достичь желаемого — пожелай достигнутого.
Здравствуйте, icWasya, Вы писали: W>Насколько опасен такой код
Код очень опасен. Он вас "с головой" выдаёт. Имена classA, classB, переменная classB* bB много говорят об авторе... Да и в целом — код не компилируется.
Если же вы хотели спросить про warning C4355, то его можно игнорировать да тех пор пока в конструкторе classA::classA(classB* bB) не вызываются методы класса classB.
Скрытый текст
W>
W>class B;//тут, видимо, должна была быть декларация class classB;, без которой этот код вообще не должен компилироваться.
W>class classA{
W>public:
W> classA(classB* bB):B(bB){;}
W> operator int(void){return FB->value;}//???
W>private:
W> classB* B;
W>};
W>class classB{
W>friend classA;
W>public:
W> classA* A;
W> classB():value(0),
W> A(this)// <<==---- warning C4355
W> {;}
W>private:
W> int value;
W>};
W>main()
W>{
W> classB B;
W> int value = B.A;
W>}
W>
Здравствуйте, icWasya, Вы писали:
W>Насколько опасен такой код
именно в данном коде проблем не вижу, кроме того, что он не скомпилируется из-за FB->value
однако дополню:
1. мемберы класса инициализируются в порядке _объявления_, а не в порядке, указанном в списке инициализации
classB():value(0),
A(this)
здесь сначала выставится A(this), а лишь потом value занулится, т.к. это соответствует порядку объявления мемберов класса classB
2. передавать this в списке инициализации куда-то _может быть иногда_ опасно (приводить к проблемам), т.к. его могут использовать еще до окончания работы конструктора. и тут могут быть сюрпризы на этапе выполнения. поэтому и выдается предупреждение, чтобы уберечь от подобных проблем
Действительно не компилируется — выдирал не проверяя
На самом деле классы шаблонные
Вот это компилируется и даже наботает
template<class T>
class classB;
template<class T>
class classA{
public:
classA(classB<T>* bB):B(bB){;}
operator int (void){return B->value;}
private:
classA(){;}
classB<T>* B;
}; // Класс classA именно такой и в нём больше ничего нетtemplate<class T>
class classB{
friend classA<T>;
public:
classA<T> A;
classB():value(0),
A(this)// <<==---- warning C4355
{;}
public:
/* тут другие методы*/private:
/* тут другие поля */private:
int value;
};
Здравствуйте, rg45, Вы писали: R>Здравствуйте, icWasya, Вы писали:
W>>Насколько опасен такой код R>
Использование this в списке инициализации
R>Цитата из MSDN: R>
R>The base-class constructors and class member constructors are called before this constructor. In effect, you've passed a pointer to an unconstructed object to another constructor. If those other constructors access any members or call member functions on this, the result will be undefined. You should not use the this pointer until all construction has completed.
R>Звучит это довольно странно, поскольку , согласно стандарту, сконструированным объект может считаться только после завершения работы конструктора (конструкторов всех уровней иерархии начледования). С этой точки зрения использование this в теле конструктора ни чем не лучше, чем в списке инициализации. Однако при использовании this в теле конструктора данное предупреждение не возникает. В целом, предупреждение достаточно бесполезное.
Тут не соглашусь, ибо в теле конструктора:
1. Гарантировано вызваны конструкторы родителей.
2. Гарантировано проинициализированы члены класса.
Т.е. объект валиден. Даже если не рассматривать множественное наследование, граблей можно все равно отгрести.
Здравствуйте, saf_e, Вы писали:
_>Здравствуйте, rg45, Вы писали:
R>>Здравствуйте, icWasya, Вы писали:
_>2. Гарантировано проинициализированы члены класса.
не большой спец в плюсах, но насколько я знаю, при таком вызове контруктора my_class * p = new my_class; POD члены НЕ будут проинициализированы.
Здравствуйте, Jack128, Вы писали:
J>не большой спец в плюсах, но насколько я знаю, при таком вызове контруктора my_class * p = new my_class; POD члены НЕ будут проинициализированы.
Здравствуйте, saf_e, Вы писали:
R>>Звучит это довольно странно, поскольку , согласно стандарту, сконструированным объект может считаться только после завершения работы конструктора (конструкторов всех уровней иерархии начледования). С этой точки зрения использование this в теле конструктора ни чем не лучше, чем в списке инициализации. Однако при использовании this в теле конструктора данное предупреждение не возникает. В целом, предупреждение достаточно бесполезное.
_>Тут не соглашусь, ибо в теле конструктора:
_>1. Гарантировано вызваны конструкторы родителей. _>2. Гарантировано проинициализированы члены класса.
_>Т.е. объект валиден...
Далеко не всегда. Время жизни объекта, согласно стандарту (п.3.8/1) начинается только после завершения его инициализации, т.о. говорить о валидности объекта во время работы конструктора не приходится. Конечно, это не значит что в конструкторе нельзя обращаться к членам, просто делать это нужно обдумано. При бездумном же отношении неприятности можно поиметь хоть в списке инициализации, хоть в теле конструктора. И список этих неприятностей не сводится к одному лишь неосторожному обращению с this — можно, например, нарваться на тот же pure virtual call.
--
Не можешь достичь желаемого — пожелай достигнутого.