Здравствуйте, <Аноним>, Вы писали:
А>Может и простенький вопрос, но мне не понятно: А>чем плох вызов виртуального метода из конструктора?
Эта проблема называется "потерей указателя this". В наследнике переопределенный метод может обратиться к полю класса (this.*), считая, что совершает вполне легальное действие, в то время как конструктор, быть может, еще не успел инициализировать данное поле (в зависимости от кода конструктора) — и вылетит исключение обращения по пустой ссылке, к примеру. В общем случае конструктор не должен "терять this" (делать его доступным кому-либо) вплоть до своего завершения.
Здравствуйте, Аноним, Вы писали:
А>Привет всем.
А>Может и простенький вопрос, но мне не понятно: А>чем плох вызов виртуального метода из конструктора?
А>Спасибки
Скорее всего, дело в том, что пока не выполнились все конструкторы, объект полностью не сконструирован, а следовательно таблица виртуальных функций (или что там в net framework) не полностью загружена в память, и виртуальность не может быть корректно разрешена, по крайней мере так дело обстоит с С++.
Здравствуйте, denezuela, Вы писали:
А>>Может и простенький вопрос, но мне не понятно: А>>чем плох вызов виртуального метода из конструктора?
D>Скорее всего, дело в том, что пока не выполнились все конструкторы, объект полностью не сконструирован, а следовательно таблица виртуальных функций (или что там в net framework) не полностью загружена в память, и виртуальность не может быть корректно разрешена, по крайней мере так дело обстоит с С++.
Здесь не так Тут именно что поля могут быть ещё непроинициализированы.
Help will always be given at Hogwarts to those who ask for it.
Re[3]: Virtual member call in constructor. Плохо?
От:
Аноним
Дата:
30.10.07 15:02
Оценка:
Здравствуйте, _FRED_, Вы писали:
_FR>Здесь не так Тут именно что поля могут быть ещё непроинициализированы.
А разве инициализация полей дефолтовыми значениями происходит не до выполнения конструктора?
Здравствуйте, Аноним, Вы писали: А>А разве инициализация полей дефолтовыми значениями происходит не до выполнения конструктора?
Происходит. Вопрос не этом, а в том, что возможна производному классу нужна более сложная инициализация, которую выполняет еще не вызванный конструктор.
Исходя из статьи следует, что проблемы могут возникнуть только при многопоточности.
Я уже понял, что это плохая практика, но всё же интересно: однопоточному приложению это ничем не грозит?
Здравствуйте, Mab, Вы писали:
Mab>Здравствуйте, Аноним, Вы писали: А>>А разве инициализация полей дефолтовыми значениями происходит не до выполнения конструктора? Mab>Происходит. Вопрос не этом, а в том, что возможна производному классу нужна более сложная инициализация, которую выполняет еще не вызванный конструктор.
Можно ли тогда сказать, что вызов виртальных методов в конструкторе, не есть плохо, но к этому надо подходить внимательно?
Здравствуйте, <Аноним>, Вы писали:
А>Исходя из статьи следует, что проблемы могут возникнуть только при многопоточности.
Не следует, прочитайте внимательнее.
А>Я уже понял, что это плохая практика, но всё же интересно: однопоточному приложению это ничем не грозит?
Грозит.
Здравствуйте, vladpol, Вы писали:
V>Можно ли тогда сказать, что вызов виртальных методов в конструкторе, не есть плохо,
Имхо, есть, но этого часто попросту не избежать (изменение свойства "Property" формы в InitializeComponent часто приводит к вызову виртуального метода "OnPropertyChanged" :о()
V>но к этому надо подходить внимательно?
Да
Help will always be given at Hogwarts to those who ask for it.
Здравствуйте, vladpol, Вы писали:
V>Можно ли тогда сказать, что вызов виртальных методов в конструкторе, не есть плохо, но к этому надо подходить внимательно?
ИМХО да.
Здравствуйте, <Аноним>, Вы писали:
А>А разве инициализация полей дефолтовыми значениями происходит не до выполнения конструктора?
Не до завершения родительского конструктора.
Здравствуйте, vladpol, Вы писали:
V>Можно ли тогда сказать, что вызов виртальных методов в конструкторе, не есть плохо, но к этому надо подходить внимательно?
Это есть плохо и надо выжигать каленым железом. Сколь ни подходи внимательно, если указатель this опубликован, то... кто-нибудь да когда-нибудь его попытается дернуть раньше времени. И это может сделать вовсе не сам внимательный автор класса, не сам внимательный автор всей библиотеки, не самый внимательнейший автор движка или системы — а кто-то, кто не знает, о том что все они (а кое-то из них по-дурости совершенно сознательно), даже будучи внимательными, заложили в свою систему риск безопасности инициализации.
Это как ружье, что висит на стене в первом акте спектакля...
Толку от этого — чуть, часто проблемы это вызывает именно во всяких "компонентах", свойства которых любят отправлять события об их, свойств, изменении, а в производных классах свойства меняются и события "отлавливаются"
Help will always be given at Hogwarts to those who ask for it.
Здравствуйте, Аноним, Вы писали:
А>Привет всем.
А>Может и простенький вопрос, но мне не понятно: А>чем плох вызов виртуального метода из конструктора?
Плох тем, что класс-наследник может обратиться к чему угодно в этом переопределённом методе, в т.ч. к своим еще непроинициализированным полям.
Тем не менее, дизайнеры форм и компонентов генерят метод InitializeComponent, который вызывается из конструктора, и который, в свою очередь, вызывает тонны виртуальных методов или обращается к виртуальным св-вам. Об этом надо помнить, при переопределении виртуальных св-в у Control и его наследников. Иногда я прибегаю к услугам ISupportInitialize, как к более общему решению (которое накрывает и эту проблему в т.ч.)