реклама на сайте
подробности

 
 
 
Reply to this topicStart new topic
> IAR EWAVR и виртуальные функции
AlexG_changed
сообщение Nov 12 2007, 12:41
Сообщение #1


Участник
*

Группа: Validating
Сообщений: 64
Регистрация: 16-06-05
Пользователь №: 6 073



Компилятор IAR EWAVR 4.20A
Микроконтроллер ATmega128

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

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

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

(отлаживаю под JTAG ICE)

Сообщение отредактировал AlexG - Nov 12 2007, 12:47
Go to the top of the page
 
+Quote Post
alexander55
сообщение Nov 12 2007, 13:00
Сообщение #2


Бывалый
*****

Группа: Свой
Сообщений: 1 584
Регистрация: 7-08-07
Пользователь №: 29 615



Цитата(AlexG @ Nov 12 2007, 15:41) *

Приведите какой-нибудь текст (объявления, наследования и использование), а то пока разговор абстрактный. 07.gif
Go to the top of the page
 
+Quote Post
AlexG_changed
сообщение Nov 13 2007, 04:10
Сообщение #3


Участник
*

Группа: Validating
Сообщений: 64
Регистрация: 16-06-05
Пользователь №: 6 073



Разобрался. Вызывать виртуальную функцию прямо в конструкторе класса было неудачной идеей.
Go to the top of the page
 
+Quote Post
Непомнящий Евген...
сообщение Nov 15 2007, 06:38
Сообщение #4


Знающий
****

Группа: Свой
Сообщений: 771
Регистрация: 16-07-07
Из: Волгодонск
Пользователь №: 29 153



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

Был тот же косяк... IAR вначале вызывает конструктор, а потом инициализирует указатель __vptr smile.gif Не совсем понятно, почему так сделали.
Go to the top of the page
 
+Quote Post
dxp
сообщение Nov 15 2007, 07:06
Сообщение #5


Adept
******

Группа: Свой
Сообщений: 3 469
Регистрация: 6-12-04
Из: Novosibirsk
Пользователь №: 1 343



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

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

Вызов кода, рабтающего с собственным представлением, из конструктора всегда опасен и чреват ошибками, т.к. объект еще недостроен, а его уже юзают.


--------------------
«Отыщи всему начало, и ты многое поймёшь» К. Прутков
Go to the top of the page
 
+Quote Post
Непомнящий Евген...
сообщение Nov 18 2007, 08:54
Сообщение #6


Знающий
****

Группа: Свой
Сообщений: 771
Регистрация: 16-07-07
Из: Волгодонск
Пользователь №: 29 153



А почему нельзя инициализировать его до выполнения конструктора - компилятор то уже знает, где этот указатель лежит и чему должен быть равен?
Go to the top of the page
 
+Quote Post
dxp
сообщение Nov 18 2007, 12:11
Сообщение #7


Adept
******

Группа: Свой
Сообщений: 3 469
Регистрация: 6-12-04
Из: Novosibirsk
Пользователь №: 1 343



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

Код
class TSlon { ... }

...

TSlon *p = new TSlon;


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

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

Объект в С++ конструируется только конструктором и никак иначе. Все остльные варианты реалиации - это лазейки для нетривиальных глюков.


--------------------
«Отыщи всему начало, и ты многое поймёшь» К. Прутков
Go to the top of the page
 
+Quote Post
Николай Z
сообщение Nov 18 2007, 12:46
Сообщение #8


Местный
***

Группа: Участник*
Сообщений: 418
Регистрация: 20-08-07
Пользователь №: 29 930



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


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

В лучшем случае компилятор знает где будет лежать указатель на создаваемый объект, а указатель этот - до конструктора как правило просто пустой. И объекта еще нет...
Go to the top of the page
 
+Quote Post
Непомнящий Евген...
сообщение Nov 18 2007, 13:17
Сообщение #9


Знающий
****

Группа: Свой
Сообщений: 771
Регистрация: 16-07-07
Из: Волгодонск
Пользователь №: 29 153



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

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


Когда вы пишите TSlon *p = new TSlon, то вначале вызывается operator new(), затем контсруктор TSlon и только затем инициализируется __vptr. Не до конца понятно, почему нельзя инициализировать __vptr до вызова конструктора - указатель на память, где будет расположен объект, уже есть.
Go to the top of the page
 
+Quote Post
IgorKossak
сообщение Nov 18 2007, 14:58
Сообщение #10


Шаман
******

Группа: Модераторы
Сообщений: 3 064
Регистрация: 30-06-04
Из: Киев, Украина
Пользователь №: 221



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

Ну и на что должен указывать этот указатель? На обьект, который там скоро появится?
Напоминает фразу: "Вы жарьте, а рыба будет".
Go to the top of the page
 
+Quote Post
Непомнящий Евген...
сообщение Nov 19 2007, 07:01
Сообщение #11


Знающий
****

Группа: Свой
Сообщений: 771
Регистрация: 16-07-07
Из: Волгодонск
Пользователь №: 29 153



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

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

После вызова operator new уже есть указатель на (неиниализированную) память. В этой точке также известна структура создаваемого объекта и его тип - т.е. известно, чему равен __vptr и где он находится. Почему нельзя его записать до вызова пользовательского конструктора, а не после?
Go to the top of the page
 
+Quote Post
alexander55
сообщение Nov 19 2007, 07:23
Сообщение #12


Бывалый
*****

Группа: Свой
Сообщений: 1 584
Регистрация: 7-08-07
Пользователь №: 29 615



Цитата(Непомнящий Евгений @ Nov 19 2007, 10:01) *

Объект условно состоит из:
- свойств (память типа ОЗУ);
- реализаций (память типа Flash).
Создание объекта подразумевает два варианта:
1. статический объект память свойств отводится уже на этапе компиляции (она строго резервируется);
2. динамическое создание объекта (память свойств отводится в куче и она находится, там где окажется).
Go to the top of the page
 
+Quote Post
dxp
сообщение Nov 19 2007, 10:24
Сообщение #13


Adept
******

Группа: Свой
Сообщений: 3 469
Регистрация: 6-12-04
Из: Novosibirsk
Пользователь №: 1 343



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

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

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

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

Какая такая необходимость вызвать виртуальные функции на стадии конструирования объекта?


--------------------
«Отыщи всему начало, и ты многое поймёшь» К. Прутков
Go to the top of the page
 
+Quote Post
Непомнящий Евген...
сообщение Nov 19 2007, 10:38
Сообщение #14


Знающий
****

Группа: Свой
Сообщений: 771
Регистрация: 16-07-07
Из: Волгодонск
Пользователь №: 29 153



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


Ну напоролся же один раз - значит была необходимость. Когда понял в чем дело - обошелся smile.gif
Счас еще раз пересмотрел Страуструпа - не нашел указаний на то, что в конструкторе нельзя дергать виртуальные функции...
Go to the top of the page
 
+Quote Post
dxp
сообщение Nov 19 2007, 11:52
Сообщение #15


Adept
******

Группа: Свой
Сообщений: 3 469
Регистрация: 6-12-04
Из: Novosibirsk
Пользователь №: 1 343



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

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

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


--------------------
«Отыщи всему начало, и ты многое поймёшь» К. Прутков
Go to the top of the page
 
+Quote Post

Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 21st July 2025 - 21:52
Рейтинг@Mail.ru


Страница сгенерированна за 0.01493 секунд с 7
ELECTRONIX ©2004-2016