Logo Море(!) аналитической информации!
IT-консалтинг Software Engineering Программирование СУБД Безопасность Internet Сети Операционные системы Hardware
Архив форумов ЦИТФорума
Море(!) вопросов - Море(!) ответов
 
 FAQFAQ   ПоискПоиск   ПользователиПользователи   ГруппыГруппы   РегистрацияРегистрация 
 ПрофильПрофиль   Войти и проверить личные сообщенияВойти и проверить личные сообщения   ВходВход 
Как правильно задавать вопросы

Полиморфизм зависит от конструктора!

 
Перейти:  
Этот форум закрыт, вы не можете писать новые сообщения и редактировать старые.   Эта тема закрыта, вы не можете писать ответы и редактировать сообщения.    Список форумов Архив форумов ЦИТФорума -> Программирование
Предыдущая тема :: Следующая тема  
Автор Сообщение
Aldor__
Гость





СообщениеДобавлено: Ср Май 05 2004 20:47    Заголовок сообщения: Полиморфизм зависит от конструктора! Ответить с цитатой

Имеются два класса: предок и потомок (CBase и CDerivative). У обоих объявлен и реализован виртуальный метод VirMethod(). В виртуальном методе потомка вызывается этот же метод предка.
У предка имеется публичный метод CallVirMethod(), который вызывает этот самый виртуальный метод.
Так же имеется два типа конструкторов: с параметром и без параметра

Код:

class CBase
{
private:
  int itsNum;
protected:
  virtual void VirMethod()
  {
    printf("CBase\n");
  };
public:
  CBase() {};
  CBase(int Num)
  {
    itsNum = Num;
  };
  void CallVirMethod()
  {
    VirMethod();
  };
};

class CDerivative: public CBase
{
protected:
  virtual void VirMethod()
  {
    CBase::VirMethod();
    printf("CDerivative\n");
  };
public:
  CDerivative() {};
  CDerivative(int Num)
  {
    CBase::CBase(Num);
  };
};

int main()
{
  CBase *pCls = new CDerivative();
  pCls->CallVirMethod();
  return 0;
}



Вот в таком случае виртуальный метод Method() вызывается действительно полиморфно.
В итоге в консоли будет:
CBase
CDerivative

Если же создать класс так:
Код:

  CBase *pCls = new CDerivative(SomeInteger);



То никакой полиморфности! В консоли следующее:
CBase

Стабильно повторяющийся эффект: от того, какой конструктор вызывается, зависит полиморфность.
Вернуться к началу
droopy
Гость





СообщениеДобавлено: Ср Май 05 2004 21:20    Заголовок сообщения: Ответить с цитатой

у тебя наверное преотвратнейший компилятор.
мой vc++6.0 компилирует нормально и работает все верно.
Вернуться к началу
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. извините за словесный понос
Вернуться к началу
Посмотреть профиль Отправить личное сообщение
Показать сообщения:   
Этот форум закрыт, вы не можете писать новые сообщения и редактировать старые.   Эта тема закрыта, вы не можете писать ответы и редактировать сообщения.    Список форумов Архив форумов ЦИТФорума -> Программирование Часовой пояс: GMT + 3
Страница 1 из 1

 
Перейти:  
Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах


Powered by phpBB © 2001, 2002 phpBB Group
Русская поддержка phpBB

 

IT-консалтинг Software Engineering Программирование СУБД Безопасность Internet Сети Операционные системы Hardware

Информация для рекламодателей PR-акции, размещение рекламы — adv@citforum.ru,
тел. +7 495 6608306, ICQ 232284597
Пресс-релизы — pr@citforum.ru
Послать комментарий
Информация для авторов
This Web server launched on February 24, 1997
Copyright © 1997-2000 CIT, © 2001-2006 CIT Forum
Внимание! Любой из материалов, опубликованных на этом сервере, не может быть воспроизведен в какой бы то ни было форме и какими бы то ни было средствами без письменного разрешения владельцев авторских прав. Подробнее...