Виртуальные функции. Проблема

 

Есть 4 класса 

//+------------------------------------------------------------------+
class Food
{
public:
   string Type() { return "Food"; }
};

//+------------------------------------------------------------------+
class FastFood
{
public:
   virtual Food* GetFood() { return new Food(); }
};

//+------------------------------------------------------------------+
class Burger : public Food
{
public:
   string Type() { return "Burger"; }
};

//+------------------------------------------------------------------+
class McDonalds : public FastFood
{
public:
   virtual Food* GetFood() { return new Burger(); }
};

 Проверяю

   McDonalds mcd;
   Food* f = mcd.GetFood();
   Print(f.Type());
   delete f;

 Выводит Food. Ожидалось Burger.

Как решить проблему? Возможно я использую неправильный синтаксис виртуальных функций?

Документация по MQL5: Основы языка / Объектно-ориентированное программирование / Виртуальные функции
Документация по MQL5: Основы языка / Объектно-ориентированное программирование / Виртуальные функции
  • www.mql5.com
Основы языка / Объектно-ориентированное программирование / Виртуальные функции - Документация по MQL5
 
GarF1eld писал(а)  :

Есть 4 класса 

 Проверяю

 Выводит Food. Ожидалось Burger.

Как решить проблему? Возможно я использую неправильный синтаксис виртуальных функций?

А функция Type() разве виртуальная?

Food *f = ...
Тип переменной f есть "указатель на Food", назовём его "статическим типом" f.
Сама переменная может "указывать", то есть хранить handle объекта типа, производного от Food, назовём этот тип в тот момент времени, когда f хранит handle объекта этого типа, "динамическим типом" f.
В данном примере в интересующий момент времени "динамический тип" f есть Burger.

Вызов:
f.Type();
есть вызов "статический тип"::Type(), - в данном случае Food::Type(), - если функция Type() НЕ виртуальная; либо "динамический тип"::Type(), - в данном случае Burger::Type(), - если функция виртуальная.
В данном примере функция Type() - НЕ виртуальная, поэтому происходит вызов Food::Type().

Думаю, теперь ответ на вопрос, как решить проблему, ясен.
 
simpleton:

А функция Type() разве виртуальная?

Точно! Ее ж нужно тоже сделать виртуальной. Спасибо! Буду дальше разбираться, потому что у меня тут конструкция немного сложнее :)
 

Опять нужна помощь. Есть такие классы 

//------------------------------------------------
class CParameters
{
public:
   int IntItems[2];
};

//------------------------------------------------
class CFunction
{
protected:
  virtual CParameters* CreateParameters() { return NULL; } 
  
public:
   CFunction() { parameters = CreateParameters(); }
   
   CParameters* parameters;
};

//------------------------------------------------
//------------------------------------------------
class CMyParameters : public CParameters 
{
public:
   string StringItems[2];
};

//------------------------------------------------
class CMyFunction : public CFunction
{
protected:
  virtual CParameters* CreateParameters() { return new CMyParameters(); } 
  
public:
   CParameters* parameters;
};

 И код:

void OnStart()
{
   CMyFunction* func = new CMyFunction();
   CMyParameters* pars = func.parameters;
   pars.StringItems[0] = "test";  // тут вылетает т.к pars = NULL
}

 Вылетает на последней строчке. 

Основная идея кода, чтобы пользователь мог насдледоваться от CFunction и переопределять всего-лишь один метод CreateParameters(). А вся логика будет выполняться в базовом классе, только с экземпляром, созданным CreateParameters().

Такое вообще реально?

 

 

Если добавить метод CFunction::ReturnParameters 

   virtual CParameters* ReturnParameters() 
   { 
      parameters = CreateParameters(); 
      return parameters; 
   }

 и написать так

   CMyFunction* func = new CMyFunction();
   CMyParameters* pars2 = func.ReturnParameters();
   CMyParameters* pars1 = func.parameters;

 То в pars2 оказывается объект, а pars1 = NULL :) В с++ аналогично. Я в замешательстве...

 
GarF1eld:

Если добавить метод CFunction::ReturnParameters 

 и написать так

 То в pars2 оказывается объект, а pars1 = NULL :) В с++ аналогично. Я в замешательстве...

Виртуальности в конструкторе нет.

Нельзя вызывать метод потомка из вызова конструирования родителя, т.к. потомок ещё не сконструирован (вот как то так примерно).

 
mql5:

Виртуальности в конструкторе нет.

Нельзя вызывать метод потомка из вызова конструирования родителя, т.к. потомок ещё не сконструирован (вот как то так примерно).

Да, с этим я уже разобрался. Но что насчет функции ReturnParameters(), которая создает и возвращает parameters в то время, как последующий прямой доступ к parameters вернет NULL??

Сам же отвечаю:  в  CMyFunction повторно объявлены parameters. Поэтому так случается.

 

Вопрос решен :) 

Причина обращения: