А>При создании объекта класса ChildClass мы не попадаем в его Init, а идем через Init базового. Я что-то туплю, как-то я не так думал... А>Это так надо?
В дочернем классе Init в конструкторе не вызывается. В родительском классе вызывается Init, не виртуальный, следовательно Base::Init. А виртуальным Init делать нельзя, так как в конструкторе вызывать виртуальные ф-ции нельзя.
Re: Не понял. Что за ерунда. Это так и должно быть?
а ты как думаешь?
если логически: ты начал строить ChildClass (про порядок конструирования надеюсь знаешь?) а строится начал пока что только Base — можно ли разрешать что то делать с методами ChildClass?
если технически: то таблица адресов виртуальных функций к этому моменту ещё не проинициализированна правильными адресами.
Re: Не понял. Что за ерунда. Это так и должно быть?
Здравствуйте, Аноним, Вы писали:
А>При создании объекта класса ChildClass мы не попадаем в его Init, а идем через Init базового. Я что-то туплю, как-то я не так думал... :( А>Это так надо?
Это принципиальное решение в C++: конструирование идёт по цепочке иерархии, и на момент вызова конструктора некоторого класса X таблица виртуальных функций содержит те методы, которые описаны в X, а не в том классе, конструирование объекта которого было заказано изначально. Да, это отличается от многих других языков, где сделано, что эта таблица содержит только финальные методы (в смысле, того класса, который заказан).
Страуструп в своей книге обосновывал это решение, можешь почитать.
(Кстати, с деструкторами точно так же — в деструкторе перекрытия методов потомками уже не видны.)
Если этот вариант не подходит, существуют другие решения: например, строить "пустой" объект и дальше вызывать заполнение целевыми данными отдельной функцией — не конструктором.
The God is real, unless declared integer.
Re[2]: Не понял. Что за ерунда. Это так и должно быть?
Здравствуйте, nen777w, Вы писали:
N>а ты как думаешь? N>если логически: ты начал строить ChildClass (про порядок конструирования надеюсь знаешь?) а строится начал пока что только Base — можно ли разрешать что то делать с методами ChildClass?
Ну вообще-то можно (например, в Object Pascal и его борландовских клонах сделано именно так — изначально видны методы целевого класса, VMT задаётся один раз и не меняется). Это просто другой дизайн.
The God is real, unless declared integer.
Re[3]: Не понял. Что за ерунда. Это так и должно быть?
Здравствуйте, netch80, Вы писали:
N>Здравствуйте, nen777w, Вы писали:
N>>а ты как думаешь? N>>если логически: ты начал строить ChildClass (про порядок конструирования надеюсь знаешь?) а строится начал пока что только Base — можно ли разрешать что то делать с методами ChildClass?
N>Ну вообще-то можно (например, в Object Pascal и его борландовских клонах сделано именно так — изначально видны методы целевого класса, VMT задаётся один раз и не меняется). Это просто другой дизайн.
гм... интересно не знал. а что там порядок конструирования тоже другой?
иначе не очень понятно смысла такого
Re: Не понял. Что за ерунда. Это так и должно быть?
Неоконченная мысль всегда казалась Шри Япутре слишком
Re: Не понял. Что за ерунда. Это так и должно быть?
От:
Аноним
Дата:
28.08.11 09:47
Оценка:
Здравствуйте, Аноним, Вы писали:
А>При создании объекта класса ChildClass мы не попадаем в его Init, а идем через Init базового. Я что-то туплю, как-то я не так думал... А>Это так надо?
Ты нашел засаду, которую устроил веселый дядька Страуструп! В этом языке много таких неожиданных шуток и веселых розыгрышей, именно поэтому язык C++ был так популярен долгое время, и до сих пор его многие любят! Изучай C++ и тебя ждет еще немало забавных открытий!
Re[4]: Не понял. Что за ерунда. Это так и должно быть?
Здравствуйте, nen777w, Вы писали:
N>>Ну вообще-то можно (например, в Object Pascal и его борландовских клонах сделано именно так — изначально видны методы целевого класса, VMT задаётся один раз и не меняется). Это просто другой дизайн. N>гм... интересно не знал. а что там порядок конструирования тоже другой? N>иначе не очень понятно смысла такого
Прикинь, да! И в C# и джаве так же! Потому что их разрабатывали унылые люди без чувства юмора.
Вообще, в C# и джаве такое возможно, потому что там есть принудительная инициализация всех полей по умолчанию, так что совсем неинициалированный объект в конструкторе получить не удастся.
Для C++, мне кажется, в идеале нужно было бы иметь по два конструктора и деструктора. Второй конструктор — что-то типа зарезервированной функции void on_created(), и деструктор что-то типа on_destroying(), потому что иначе изнутри объекта получить эквивалент таких событий просто невозможно и иногда это создает проблемы.
Re[4]: Не понял. Что за ерунда. Это так и должно быть?
Здравствуйте, nen777w, Вы писали:
N>>>а ты как думаешь? N>>>если логически: ты начал строить ChildClass (про порядок конструирования надеюсь знаешь?) а строится начал пока что только Base — можно ли разрешать что то делать с методами ChildClass?
N>>Ну вообще-то можно (например, в Object Pascal и его борландовских клонах сделано именно так — изначально видны методы целевого класса, VMT задаётся один раз и не меняется). Это просто другой дизайн. N>гм... интересно не знал. а что там порядок конструирования тоже другой?
Насколько я помню, там порядок конструирования решается явно — то есть конструктор потомка должен содержать инструкцию вызова конструктора предка в явном виде. Принудительного вызова "до", как в C++, там нет. Но я тут точно не уверен, давно было, и что-то с утра не соображу, где пример кода взять.
N>иначе не очень понятно смысла такого
Ну а чем плохо? Вариант C++ тоже смущает — например, если надо для конструктора предка вычислить два параметра одновременно и эффективно (не дублируя работу) на основе одних и тех же данных из конструктора потомка, то начинаются совершенно идиотские пляски.
The God is real, unless declared integer.
Re[5]: Не понял. Что за ерунда. Это так и должно быть?
Здравствуйте, Аноним, Вы писали:
А>Прикинь, да! И в C# и джаве так же! Потому что их разрабатывали унылые люди без чувства юмора.
А>Вообще, в C# и джаве такое возможно, потому что там есть принудительная инициализация всех полей по умолчанию, так что совсем неинициалированный объект в конструкторе получить не удастся.
"совсем неинициалированный" — это как? А бывает несовсем неинициалированный?
Главное гармония ...
Re[6]: Не понял. Что за ерунда. Это так и должно быть?
Здравствуйте, Mazay, Вы писали:
M>"совсем неинициалированный" — это как? А бывает несовсем неинициалированный?
Ну например, варианты существования объекта:
1) память выделена под объект, но ни один конструктор или инициализатор не вызван, память заполнена мусором (совсем неинициализированный),
2) для некоторых полей были вызваны конструкторы по умолчанию, те, у которых их нет — заполнены мусором (default initialization в C++, в C# и Java не бывает),
3) дефолтная инициализация (нулями или bool — false, как результат value initialization в С++, в C# и Java вызывается всегда),
4) частично инициализированный объект после вызова части конструкторов базовых классов,
5) полностью инициализированный объект с корректным инвариантом.
Re: Не понял. Что за ерунда. Это так и должно быть?
Здравствуйте, Аноним, Вы писали:
А>При создании объекта класса ChildClass мы не попадаем в его Init, а идем через Init базового. Я что-то туплю, как-то я не так думал... А>Это так надо?
Это ты еще не видел виртуальный деструктор...
Re: Не понял. Что за ерунда. Это так и должно быть?
А>При создании объекта класса ChildClass мы не попадаем в его Init, а идем через Init базового. Я что-то туплю, как-то я не так думал... А>Это так надо?
Вроде так опасно делать т.к. члены класса ChildClass будут не проинициализированы или даже не созданы, кроме того, зачем тебе этот инит нужен если есть конструктор?
Sic luceat lux!
Re[2]: Не понял. Что за ерунда. Это так и должно быть?
Здравствуйте, sc, Вы писали:
sc>В дочернем классе Init в конструкторе не вызывается. В родительском классе вызывается Init, не виртуальный, следовательно Base::Init. А виртуальным Init делать нельзя, так как в конструкторе вызывать виртуальные ф-ции нельзя.
Интересно, а чего это у нас rm822 минусует? С чем конкретно несогласие? Конструктор и деструктор — особый народ, виртуальные вызовы там неуместны.
Re[3]: Не понял. Что за ерунда. Это так и должно быть?
Здравствуйте, Mr.Delphist, Вы писали:
MD>Здравствуйте, sc, Вы писали:
sc>>В дочернем классе Init в конструкторе не вызывается. В родительском классе вызывается Init, не виртуальный, следовательно Base::Init. А виртуальным Init делать нельзя, так как в конструкторе вызывать виртуальные ф-ции нельзя.
MD>Интересно, а чего это у нас rm822 минусует? С чем конкретно несогласие? Конструктор и деструктор — особый народ, виртуальные вызовы там неуместны.
Ну с полной неуместностью я бы поспорил, использовать их достаточно разумно (это уж я не вспоминаю, что собственно виртуальный деструктор является стандартным приёмом).
Но грабельки надо учитывать.