Здравствуйте, _Winnie, Вы писали:
_W>Можно так, менять поля наследника до вызова контруктора? Нужно в наследнике создать битовый массив признаков из тех, от кого он отнаследован.
Ну судя по всему список возможных базовых классов известен заранее.
Так почему бы не заполнять его каким нибудь is_derivied<T,U> ?
Здравствуйте, _Winnie, Вы писали:
_W>Можно так, менять поля наследника до вызова контруктора? Нужно в наследнике создать битовый массив признаков из тех, от кого он отнаследован.
_W>
_Winnie wrote:
> Можно так, менять поля наследника до вызова контруктора? Нужно в наследнике создать битовый массив признаков из тех, от кого он отнаследован.
На практике это, скорее всего, будет работать, но зачем?
-- Maxim Yegorushkin
Posted via RSDN NNTP Server 1.9
Re: Чеширский кот и изменение наследника до конструктора
От:
Аноним
Дата:
01.09.05 18:10
Оценка:
Здравствуйте, _Winnie, Вы писали:
_W>Можно так, менять поля наследника до вызова контруктора? Нужно в наследнике создать битовый массив признаков из тех, от кого он отнаследован.
_W>
При вызове конструктора базового класса объект Derived еще не существует и обращение к его полям противоречит стандарту. Хотя этот код выполнится без всяких проблем, после завершения конструктора Base, сработает конструктор по умолчанию для Derived и, соответсвенно, конструктор по умолчанию для type_tag, после которого он будет равен 0.
Можно попробовать написать свой конструктор для Derived и не инициализировать type_tag:
// Грязный хак:
// код для Baseclass Derived: public Base<Derived>
{
public:
Derived() {} // отсутсвует инициализация type_tag;int type_tag;
};
The last good thing written in C was Franz Schubert's Symphony No. 9.
Re[2]: Чеширский кот и изменение наследника до конструктора
[]
C>При вызове конструктора базового класса объект Derived еще не существует и обращение к его полям противоречит стандарту. Хотя этот код выполнится без всяких проблем, после завершения конструктора Base, сработает конструктор по умолчанию для Derived и, соответсвенно, конструктор по умолчанию для type_tag, после которого он будет равен 0.
Сгенеренный компилятором ктор по умолчанию не обнуляет члены встроенных типов.
Re[3]: Чеширский кот и изменение наследника до конструктора
Здравствуйте, MaximE, Вы писали:
ME>Здравствуйте, crable, Вы писали:
ME>[]
C>>При вызове конструктора базового класса объект Derived еще не существует и обращение к его полям противоречит стандарту. Хотя этот код выполнится без всяких проблем, после завершения конструктора Base, сработает конструктор по умолчанию для Derived и, соответсвенно, конструктор по умолчанию для type_tag, после которого он будет равен 0.
ME>Сгенеренный компилятором ктор по умолчанию не обнуляет члены встроенных типов.
ошибочка вышла...
The last good thing written in C was Franz Schubert's Symphony No. 9.
Re[2]: Чеширский кот и изменение наследника до конструктора
Здравствуйте, MaximE, Вы писали:
ME>_Winnie wrote:
>> Можно так, менять поля наследника до вызова контруктора? Нужно в наследнике создать битовый массив признаков из тех, от кого он отнаследован.
ME>но зачем?
Что бы в runtime проверить из каких компонентов состоит объект неизвестного типа. Объект собирается из них, как из конструктора, но имеет базовый фиксированный класс, из которого полиморфно можно проверить, из чего состоит наследник. На самом деле type_tag находится в это базовом классе.
Но интересно, не запрещает ли стандарт делать static_cast к наследнику, если он еще не сконструирован. Чисто академический интерес
Правильно работающая программа — просто частный случай Undefined Behavior
Re[3]: Чеширский кот и изменение наследника до конструктора
Здравствуйте, _Winnie, Вы писали:
_W>Что бы в runtime проверить из каких компонентов состоит объект неизвестного типа. Объект собирается из них, как из конструктора, но имеет базовый фиксированный класс, из которого полиморфно можно проверить, из чего состоит наследник. На самом деле type_tag находится в это базовом классе. А rtti не лучше подойдет?
_W>Но интересно, не запрещает ли стандарт делать static_cast к наследнику, если он еще не сконструирован. Чисто академический интерес
Из чисто академического интереса порылся в стандарте ( хорошее упражнение )
5.2.9/8
An rvalue of type “pointer to cv1 B”, where B is a class type, can be converted to an rvalue of type “pointer
to cv2 D”, where D is a class derived (clause 10) from B.... If the rvalue of type “pointer to cv1 B” points to a B that is actually a sub-object of an object of type D, the resulting pointer points to the enclosing object of type D. Otherwise, the result of the
cast is undefined.
3.8/1
The lifetime of an object is a runtime property of the object. The lifetime of an object of type T begins
when:
— storage with the proper alignment and size for type T is obtained, and
— if T is a class type with a non-trivial constructor (12.1), the constructor call has completed.
3.8/5
Before the lifetime of an object has started but after the storage which the object will occupy has been allocated ... If the object will be or was of a non-POD class type, the program has
undefined behavior if:
— the pointer is used to access a non-static data member or call a non-static member function of the object,
Мне кажется, что на основании приведенных цитат можно судить, что формально имеем UB.
До того, как закончится конструирование объекта производного класса, нельзя утверждать, что B is actually a sub-object of an object of type D, т.к. объекта типа D еще не существует, так что само преобразование уже является UB. Во-вторых, даже если мы волшебным образом получили валидный указатель, срабатывает 3.8/5.