grayrat
Зарегистрирован: 30.06.2003 Сообщения: 189
|
Добавлено: Пт Май 07 2004 13:29 Заголовок сообщения: Всё правильно работает !!! |
|
|
Ты явно вызываешь в конструкторе наследника конструктор предка. Конструктор предка помимо установки нужного значения переменной
itsNum (это нельзя назвать инициализацией) ещё модифицирует таблицу виртуальных методов, т.е. вставляет в неё адрес СВОЕГО виртуального метода, и поэтому он и будет вызываться. Инициализация базового класса делается по другому:
Код: | CDerivative(int Num) :CBase(Num)
{}; |
Потому что случае сначала вызывается конструктор предка, потом происходит инициализация таблицы виртуальных методов наследника, переменных (новых) наследника и потом работает тело конструктора наследника.
В твоём варианте:
Код: | CDerivative(int Num)
{
CBase::CBase(Num);
}; |
Сначала вызывается конструктор по умолчанию базового класса (можешь проверить) потом инициализируется (правильно) таблица виртуальных методов, потом работает тело наследника в котором вызывается конструктор базового класса и херит VMT
К слову, члены данные тоже желательно инициализировать так:
Код: | CBase(int Num) : itsNum( Num )
{}; |
Если присваивать в конструкторе, возможно новый компилятор и соптимизирует, а возможно сперва инициализирует нулём или какой-нибудь фигнёй, а потом присвоит данное тобой значение. Особенно это важно если член данное - класс. Если его инициализировать после двоеточия, то сразу при создании объекта будет вызван нужный конструктор, если присваивать - то, если не определён специальный оператор присваивания, то сперва будет создан временный объект проинициализированный твоими данными, затем произойдёт его копирование.
Тот факт что приведённый тобой код на более новых компиляторах работает так как ты хочешь, говорит о том что более новые компиляторы лучше оптимизируют. Наверняка ты не первый наступил на эти грабли и создатели компиляторов это учли.
PS. извините за словесный понос |
|