Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: IAR EWAVR и виртуальные функции
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > Cредства разработки для МК > IAR
AlexG_changed
Компилятор IAR EWAVR 4.20A
Микроконтроллер ATmega128

В программе есть родительский класс и два наследованных от него класса, отличающихся парой функций.
При объявлении соответствующих функций родительского класса виртуальными программа виснет где-то между __low_level_init() и main(). Если сделать функции не виртуальными, то программа работает, но вызываются функции родительского класса, а не наследованных, что делает использование наследования в данном случае бессмысленным.

В чем может быть причина полной неработоспособности программы с виртуальными функциями?

После очередной перекомпиляции еще интереснее:
The application aborted
Program exit reached

(отлаживаю под JTAG ICE)
alexander55
Цитата(AlexG @ Nov 12 2007, 15:41) *

Приведите какой-нибудь текст (объявления, наследования и использование), а то пока разговор абстрактный. 07.gif
AlexG_changed
Разобрался. Вызывать виртуальную функцию прямо в конструкторе класса было неудачной идеей.
Непомнящий Евгений
Цитата(AlexG @ Nov 13 2007, 07:10) *
Разобрался. Вызывать виртуальную функцию прямо в конструкторе класса было неудачной идеей.

Был тот же косяк... IAR вначале вызывает конструктор, а потом инициализирует указатель __vptr smile.gif Не совсем понятно, почему так сделали.
dxp
Цитата(Непомнящий Евгений @ Nov 15 2007, 12:38) *
Был тот же косяк... IAR вначале вызывает конструктор, а потом инициализирует указатель __vptr smile.gif Не совсем понятно, почему так сделали.

А где по-вашему должно инициализировать указатель vptr?

Вызов кода, рабтающего с собственным представлением, из конструктора всегда опасен и чреват ошибками, т.к. объект еще недостроен, а его уже юзают.
Непомнящий Евгений
А почему нельзя инициализировать его до выполнения конструктора - компилятор то уже знает, где этот указатель лежит и чему должен быть равен?
dxp
Цитата(Непомнящий Евгений @ Nov 18 2007, 14:54) *
А почему нельзя инициализировать его до выполнения конструктора - компилятор то уже знает, где этот указатель лежит и чему должен быть равен?

Код
class TSlon { ... }

...

TSlon *p = new TSlon;


Где тут лежит объект и что об этом знает компилятор?

То же самое и в случае с созданием автоматического объекта внутри функции.

Объект в С++ конструируется только конструктором и никак иначе. Все остльные варианты реалиации - это лазейки для нетривиальных глюков.
Николай Z
Цитата(Непомнящий Евгений @ Nov 18 2007, 11:54) *
А почему нельзя инициализировать его до выполнения конструктора - компилятор то уже знает, где этот указатель лежит и чему должен быть равен?


Ничего он до выполнения конструктора не знает ибо объект вообще еще не создан и ему даже память не выделена вообще до исполнения конструктора.
Конструктор как раз и создает объект.

В лучшем случае компилятор знает где будет лежать указатель на создаваемый объект, а указатель этот - до конструктора как правило просто пустой. И объекта еще нет...
Непомнящий Евгений
Я понимаю, что такой стандарт, но все ж таки как-то неудобно. Фактически получается, что любой вызов виртуальной функции в конструкторе приводит в ошибке времени выполнения. Хотя б какой-нибудь ворнинг выдавался...

Цитата(dxp @ Nov 18 2007, 15:11) *
Где тут лежит объект и что об этом знает компилятор?


Когда вы пишите TSlon *p = new TSlon, то вначале вызывается operator new(), затем контсруктор TSlon и только затем инициализируется __vptr. Не до конца понятно, почему нельзя инициализировать __vptr до вызова конструктора - указатель на память, где будет расположен объект, уже есть.
IgorKossak
Цитата(Непомнящий Евгений @ Nov 18 2007, 15:17) *
...
Когда вы пишите TSlon *p = new TSlon, то вначале вызывается operator new(), затем контсруктор TSlon и только затем инициализируется __vptr. Не до конца понятно, почему нельзя инициализировать __vptr до вызова конструктора - указатель на память, где будет расположен объект, уже есть.

Ну и на что должен указывать этот указатель? На обьект, который там скоро появится?
Напоминает фразу: "Вы жарьте, а рыба будет".
Непомнящий Евгений
Цитата(IgorKossak @ Nov 18 2007, 17:58) *
Ну и на что должен указывать этот указатель? На обьект, который там скоро появится?
Напоминает фразу: "Вы жарьте, а рыба будет".

Указатель должен указывать на массив указателей на реализации виртуальных функции.

После вызова operator new уже есть указатель на (неиниализированную) память. В этой точке также известна структура создаваемого объекта и его тип - т.е. известно, чему равен __vptr и где он находится. Почему нельзя его записать до вызова пользовательского конструктора, а не после?
alexander55
Цитата(Непомнящий Евгений @ Nov 19 2007, 10:01) *

Объект условно состоит из:
- свойств (память типа ОЗУ);
- реализаций (память типа Flash).
Создание объекта подразумевает два варианта:
1. статический объект память свойств отводится уже на этапе компиляции (она строго резервируется);
2. динамическое создание объекта (память свойств отводится в куче и она находится, там где окажется).
dxp
Цитата(Непомнящий Евгений @ Nov 19 2007, 13:01) *
После вызова operator new уже есть указатель на (неиниализированную) память. В этой точке также известна структура создаваемого объекта и его тип

Кому известно? Пральна - конструктору. smile.gif

Цитата(Непомнящий Евгений @ Nov 19 2007, 13:01) *
- т.е. известно, чему равен __vptr и где он находится. Почему нельзя его записать до вызова пользовательского конструктора, а не после?

Потому, что по-вашему получается, что надо иметь два конструктора - один предварительный, для создания/инициализации vptr, второй - для всего остального.

Какая такая необходимость вызвать виртуальные функции на стадии конструирования объекта?
Непомнящий Евгений
Цитата(dxp @ Nov 19 2007, 13:24) *
Какая такая необходимость вызвать виртуальные функции на стадии конструирования объекта?


Ну напоролся же один раз - значит была необходимость. Когда понял в чем дело - обошелся smile.gif
Счас еще раз пересмотрел Страуструпа - не нашел указаний на то, что в конструкторе нельзя дергать виртуальные функции...
dxp
Цитата(Непомнящий Евгений @ Nov 19 2007, 16:38) *
Счас еще раз пересмотрел Страуструпа - не нашел указаний на то, что в конструкторе нельзя дергать виртуальные функции...

Наверняка вы у него не найдете и того, что не надо вызывать функцию main из других функций, но это не означает, что такоей вызов надо делать? smile.gif

Вопрос был о том, зачем вызывать виртуальную функцию из конструируемого объекта, в котором однозначно this содержит адрес текущего (этого конструируемого) объекта и будет вызваться совершенно понятно какая функция - т.е. никакой виртуальности тут нет, один только оверхед. Даже если проинициализировать vptr так, как вы хотите, виртуального по сути вызова тут не получится.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.