Использование виртуальных функций в конструкторе.

chip700
Уже с Приветом
Posts: 672
Joined: 11 Apr 2001 09:01
Location: Russia, NN

Post by chip700 »

Еще могу добавить, что изначальная задача поставлена неверно.
Вы пытаетесь написать конструктор базового класса так, что бы он подошел на все случаи жизни - то есть его код без работал без изменений для потомков.
Но ведь когда мы создаем экземпляр класса потомка, мы вызываем именно его (потомка) конструктор. Так почему бы все что нужно изменить в поведении конструктора по отношению к родительскому не добавить в конструкторе потомка.

А если позволить в конструкторе родителя вызвать перегруженный потомком метод, то он получается будет вызван до вызова конструктора потомка. А если мы там инициализируем переменные, выделяем память для каких-либо внутренних структур, которые нужны для работы нашего перегруженного метода? Таким образом придется писать каждый перегруженный метод в стиле defensive programming, обрабатывая все возможные ошибки связанные с неинициализированными полями.
А как раз смысл конструктора в классе (по Страуструпу) - ГАРАНТИРОВАТЬ всем остальным методам класса, что на момент их вызова объект полностью проинициализирован.
Димма
Уже с Приветом
Posts: 660
Joined: 01 Aug 2002 08:09

Post by Димма »

Angry wrote:Но кто-то может пояснить, почему так? Почему класс не достраивается до окончания работы конструктора?


Дык по определению. Потому что конструктор достраивает класс.
Димма
Sergei VP
Новичок
Posts: 44
Joined: 21 Mar 2003 12:44

Post by Sergei VP »

Hamster wrote:
Порядок по-моему такой:

- Выделяется память
- VFT заполняется указателями на функции базового класса ( в моем примере, класс А )
- Вызывается конструктор A::A
- VFT перезаписывается указателями на функции субкласса ( B )
- Вызывается конструктор B::B

Вам придется вводить несколько конструкторов и вызывать в разных случаях разные конструкторы, или передавать какой-нибудь флаг, чтобы сказать конструктору, что ему делать.


VFT вообще не используется в конструкторах, здесь виртуальные функции просто вызывается как обычные (невиртуальные). Поэтому и нет смысла строить VFT в run-time, что привело бы к потере эффективности, указатель на таблицу виртуальных функций определяется классом и он всегда известен на момент вызова конструктора.
Вообще-то использование виртуальных функций в конструкторах врядли можно назвать хорошей идеей, это может запутать и вас и ваших колег, так что лучше сделайте как-то по другому, воспользуйтесь паттерном фабрики класса если ваши объекты создаются только в куче (можно конечно создать через фабрику класса объект и в стеке но это немного сложнее).
User avatar
Nervous
Уже с Приветом
Posts: 7759
Joined: 18 Sep 2001 09:01
Location: RUS.76 -> KOR -> RUS.53 -> US.PA -> US.MD

Post by Nervous »

Возможно, вы будете еще раз неприятно удивлены, но и в деструкторах тоже не вызываются виртуальные методвы. По той же причине, только наоборот - объект уже частично разрушен (начиная с потомков к базам). Так шта....
N.E.R.V.O.U.S.: Networked Electronic Replicant Viable for Observation and Ultimate Sabotage.
User avatar
tengiz
Уже с Приветом
Posts: 4468
Joined: 21 Sep 2000 09:01
Location: Sammamish, WA

Post by tengiz »

Sergei VP wrote:VFT вообще не используется в конструкторах, здесь виртуальные функции просто вызывается как обычные (невиртуальные). Поэтому и нет смысла строить VFT в run-time, что привело бы к потере эффективности, указатель на таблицу виртуальных функций определяется классом и он всегда известен на момент вызова конструктора...

Виртуальную функцию можно вызвать в конструкторе (или деструкторе) не напрямую, а через вызов невиртуальной функции-члена класса, которая в свою очередь уже будет вызывать виртуальную функцию "нормальным" образом - т.е через vptr. Поэтому хочется или нет, а vptr должен быть разумным способом проинициализирован к моменту начала конструктора класса. То, что реализовано в популярных компиляторах является вполне разумным и логичным вариантом.
Cheers

Return to “Вопросы и новости IT”