Что я пропустил? Приведение типов указателей базовых классов к указателям производных классов

 

Код:

class CPattern
  {
protected:
public:
   virtual void PrintValue(){Print("CPattern");};
  };

class CPatternWW: public CPattern
  {
protected:
public:
   int Value;
   virtual void PrintValue(){Print("CPatternWW");}
  };

void OnStart()
  {
   CPattern *X;         // В последующем Массив, где будут содержаться разные классы
   X = new CPatternWW;  // Создаём класс, отличный от базового
   X.PrintValue();      // Выводит на печать CPatternWW - Полиморфизм
   X.Value = 3;         // Как привести тип указателя базового класса к указателю производного класса?
   delete X;
  }


Как мне получить доступ к X.Value?

 
Dynamic Cast мы точно не дождемся, поэтому


AlexSTAL:

Как мне получить доступ к X.Value?
Перегрузкой виртуальных функций доступа.
Документация по MQL5: Основы языка / Объектно-ориентированное программирование / Виртуальные функции
Документация по MQL5: Основы языка / Объектно-ориентированное программирование / Виртуальные функции
  • www.mql5.com
Основы языка / Объектно-ориентированное программирование / Виртуальные функции - Документация по MQL5
 
TheXpert:
Dynamic Cast мы точно не дождемся, поэтому


Перегрузкой виртуальных функций доступа.

Это первое, что я подумал...

Но если в другом классе Value должна быть к примеру структурой?

 
AlexSTAL:

Но если в другом классе Value должна быть к примеру структурой?

Вынос в базовый класс... больше пока ничего на ум не приходит.

А вообще так плохо -- инкапсуляция страдает и целостность данных частенько. Лучше таки завести методы set и get и их юзать.

 
TheXpert:

Вынос в базовый класс... больше пока ничего на ум не приходит.

А вообще так плохо -- инкапсуляция страдает и целостность данных частенько. Лучше таки завести методы set и get и их юзать.

Методы get/set где? В базовом классе именно?
 

И как понять вот это:

Приведение типов указателей базовых классов к указателям производных классов

Объекты открыто порожденного класса могут также рассматриваться как объекты соответствующего ему базового класса. Это ведет к некоторым интересным следствиям. Например, вопреки тому факту, что объекты различных классов, порожденных одним базовым классом, могут существенно отличаться друг от друга, мы можем создать их связанный список (List), поскольку мы рассматриваем их как объекты базового типа. Но обратное неверно: объекты базового класса не являются автоматически объектами производного класса.

Можно  использовать явное приведение типов для преобразования указателей базового класса в указатели производного класса. Но необходимо быть полностью уверенным в допустимости такого преобразования, так как в противном случае возникнет критическая ошибка времени выполнения и mql5-программа будет остановлена.


Документация по MQL5: Стандартные константы, перечисления и структуры / Коды ошибок и предупреждений / Ошибки времени выполнения
Документация по MQL5: Стандартные константы, перечисления и структуры / Коды ошибок и предупреждений / Ошибки времени выполнения
  • www.mql5.com
Стандартные константы, перечисления и структуры / Коды ошибок и предупреждений / Ошибки времени выполнения - Документация по MQL5
 
TheXpert:

Вынос в базовый класс... больше пока ничего на ум не приходит.

А вообще так плохо -- инкапсуляция страдает и целостность данных частенько. Лучше таки завести методы set и get и их юзать.

Ну если с методом Set такой фокус пройдёт(он всё таки имеет параметр), его можно перегрузить в базовом классе то с методом Get это не выйдет.

Метод Get призван вернуть данные( не имеет параметра) и при виртуализации его не получится перегрузить в базовом классе на разные типы.


 
Urain:

Ну если с методом Set такой фокус пройдёт(он всё таки имеет параметр), его можно перегрузить в базовом классе то с методом Get это не выйдет.

Метод Get призван вернуть данные( не имеет параметра) и при виртуализации его не получится перегрузить в базовом классе на разные типы.

Дык даже с Set не взлетит, вот этот код вернёт 11:

class CPattern
  {
protected:
public:
   virtual void SetValue(int Val){};
   virtual void PrintValue(){};
  };

class CPatternWW: public CPattern
  {
protected:
   int Value;
public:
   virtual void SetValue(int Val){Value = Val;};
   virtual void PrintValue(){Print(Value);}
  };

void OnStart()
  {
   CPattern *X;            // В последующем Массив, где будут содержаться разные классы
   X = new CPatternWW;     // Создаём класс, отличный от базового
   X.SetValue(11);
   X.PrintValue();         // Выводит на печать CPatternWW - Полиморфизм
   delete X;
  }

А вот этот уже 0:

class CPattern
  {
protected:
public:
   virtual void SetValue(char Val){};
   virtual void PrintValue(){};
  };

class CPatternWW: public CPattern
  {
protected:
   int Value;
public:
   virtual void SetValue(int Val){Value = Val;};
   virtual void PrintValue(){Print(Value);}
  };

void OnStart()
  {
   CPattern *X;            // В последующем Массив, где будут содержаться разные классы
   X = new CPatternWW;     // Создаём класс, отличный от базового
   X.SetValue(11);
   X.PrintValue();         // Выводит на печать CPatternWW - Полиморфизм
   delete X;
  }

Отличаются они 5-ой строчкой только:

   virtual void SetValue(int Val){};
   virtual void SetValue(char Val){};

Так что делать? Тупиковая ситуация?

 
AlexSTAL:

Дык даже с Set не взлетит, вот этот код вернёт 11:

А вот этот уже 0:

Отличаются они 5-ой строчкой только:

   virtual void SetValue(int Val){};
   virtual void SetValue(char Val){};

Так что делать? Тупиковая ситуация?

Я имел в виду вот так:

при true выдаст принт CPatternD 11

при false выдаст принт CPatternI 11

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
class CPattern
  {
protected:
   int               Value;
public:
   virtual void SetValue(int Val){};
   virtual void SetValue(double Val){};
   virtual void PrintValue(){};
  };
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
class CPatternI: public CPattern
  {
protected:
   int               Value;
public:
   virtual void SetValue(int Val){Value=Val;};
   virtual void PrintValue(){Print("CPatternI ",Value);}
  };
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
class CPatternD: public CPattern
  {
protected:
   double            Value;
public:
   virtual void SetValue(double Val){Value=Val;};
   virtual void PrintValue(){Print("CPatternD ",Value);}
  };
//+------------------------------------------------------------------+
//| Script program start function                                    |
//+------------------------------------------------------------------+
void OnStart()
  {
   CPattern *X;            // В последующем Массив, где будут содержаться разные классы

   if((bool)1){ X=new CPatternD; X.SetValue(11.0);}  // Создаём класс, отличный от базового
   else { X=new CPatternI; X.SetValue(11);}

   X.PrintValue();         // Выводит на печать CPatternI - Полиморфизм
   delete X;
  }

но всё равно это только для методов имеющих параметры, беспараметрические методы не перегрузишь.

 
Urain:

Я имел в виду вот так:

при true выдаст принт CPatternD 11

при false выдаст принт CPatternI 11

но всё равно это только для методов имеющих параметры, беспараметрические методы не перегрузишь.

В общем есть два варианта

  1. При данной реализации ООП это замыливание глаз - ничего глобального сотворить нельзя. Если разработчики прокомментируют - было бы здорово.
  2. Я или мои коллеги что-то не знают или что-то пропустили
Я ведь не зря привёл цитату из документации: "Можно  использовать явное приведение типов для преобразования указателей базового класса в указатели производного класса." Она же может что-то означать....
Документация по MQL5: Основы языка / Типы данных / Приведение типов
Документация по MQL5: Основы языка / Типы данных / Приведение типов
  • www.mql5.com
Основы языка / Типы данных / Приведение типов - Документация по MQL5
 
AlexSTAL:


Можно  использовать явное приведение типов для преобразования указателей базового класса в указатели производного класса.

Ого, таки можно.

Тогда как-то так:

{
   CPatternWW Y = CPatternWW(X);
   Y.Value = 1;
}