Скачать MetaTrader 5

Вопрос по ООП

Авторизуйтесь или зарегистрируйтесь, чтобы добавить комментарий
Пополняй свой счет через PayPal
Михаил Янович
190
Михаил Янович 2012.01.09 17:51 

Скажите, а возможно ли в классе потомке наряду с перегруженной функцией вызывать функцию из класса-предка?

Пример:

//--- Базовый класс
class CShape
  {
protected
   int            m_type;                // тип фигуры
   int            m_xpos;                // X - координата точки привязки
   int            m_ypos;                // Y - координата точки привязки
public:
   void           CShape(){m_type=0;};   // конструктор, тип равен нулю
   int            GetType(){return(m_type);};// возвращает тип фигуры
virtual
   double         GetArea(){return (0); }// возвращает площадь фигуры
  };

Теперь все производные классы имеют функцию-член getArea(), которая возвращает нулевое значение. Реализация этой функции в каждом потомке будет отличаться.

//--- производный класс Круг
class CCircle : public CShape            // после двоеточия указывается базовый класс,
  {                                      // от которого производится наследование 
private:
   double         m_radius;              // радиус круга
 
public:
   void           CCircle(){m_type=1;};  // конструктор, тип равен 1 
   void           SetRadius(double r){m_radius=r;};
   virtual double GetArea(){return (3.14*m_radius*m_radius);}// площадь круга
  };

Для квадрата объявление класса выглядит аналогично:

//--- производный класс Квадрат
class CSquare : public CShape            // после двоеточия указывается базовый класс,
  {                                      // от которого производится наследование 
private:
   double          m_square_side;        // сторона квадрата
 
public:
   void            CSquare(){m_type=2;}; // конструктор, тип равен 2 
   void            SetSide(double s){m_square_side=s;};
   virtual double  GetArea(){return (m_square_side*m_square_side);}//площадь квадрата
  };


То есть вызывать в  данном случае из CSquare  и CCircle не только собственные GetArea но и GetArea из CShape?

Документация по MQL5: Основы языка / Объектно-ориентированное программирование / Наследование
Документация по MQL5: Основы языка / Объектно-ориентированное программирование / Наследование
  • www.mql5.com
Основы языка / Объектно-ориентированное программирование / Наследование - Документация по MQL5
o_o
Модератор
23689
o_o 2012.01.09 17:54  

через

Родитель::Функция( )

Михаил Янович
190
Михаил Янович 2012.01.09 18:00  
Ух ты. Спасибо огромное!!! И за оперативность ответа еще большее спасибо!
Nikolay Demko
12462
Nikolay Demko 2012.01.09 18:01  
sergeev:

через

Родитель::Функция( )

А как ты в потомке вызовешь виртуальную родительскую если потомок уже имеет наследную функцию?

Разве что создать в привате потомка, композит родителя и уже из него вызвать родительскую функцию.

В общем лично я не понял твоего поста, если можно простенький пример?

o_o
Модератор
23689
o_o 2012.01.09 18:37  
Urain:

А как ты в потомке вызовешь виртуальную родительскую если потомок уже имеет наследную функцию?

В общем лично я не понял твоего поста, если можно простенький пример?

ну вот так как написал так и вызвать. на то это и делают virtual функциями, чтоб полиморфизм срабатывал.

так нельзя только деструктор вызывать, так как он автоматически сам MQL вызывается

пример из кода выше

CShape::GetArea();

сделает вызов из базового класса, то есть вернет 0.


Nikolay Demko
12462
Nikolay Demko 2012.01.09 18:56  
sergeev:

ну вот так как написал так и вызвать. на то это и делают virtual функциями, чтоб полиморфизм срабатывал.

так нельзя только деструктор вызывать, так как он автоматически сам MQL вызывается

пример из кода выше

CShape::GetArea();

сделает вызов из базового класса, то есть вернет 0.


Чёто не хочит компилиться, где я накосячил?

//+------------------------------------------------------------------+
class A
  {
public:
                     A(void){};
                    ~A(void){};
   virtual void      func(){Print(__FUNCTION__);};
  };
//+------------------------------------------------------------------+
class B : public A
  {
public:
                     B(void){};
                    ~B(void){};
   void              func(){Print(__FUNCTION__);};
  };
//+------------------------------------------------------------------+
void OnStart()
  {
   A *obj=new B();
   obj.func();
   A::func();
   delete obj;
  }
//+------------------------------------------------------------------+

ЗЫ кстати A::obj.func(); тоже не компилиться.

o_o
Модератор
23689
o_o 2012.01.09 19:28  

так и знал, что попробуешь именно так :)

родительские функции через ::  могут вызываться только в функциях потомка.

снаружи не получится.

----

и кстати, в потомке функция тоже должна быть обязательно virtual , иначе может быть проблема с падением терминала.

Nikolay Demko
12462
Nikolay Demko 2012.01.09 19:45  
sergeev:

так и знал, что попробуешь именно так :)

родительские функции через ::  могут вызываться только в функциях потомка.

снаружи не получится.

----

и кстати, в потомке функция тоже должна быть обязательно virtual , иначе может быть проблема с падением терминала.

Ага вьехал, типа вот так:

//+------------------------------------------------------------------+
class A
  {
public:
                     A(void){};
                    ~A(void){};
   virtual void       func(){Print(__FUNCTION__);};
   virtual void       func1(){Print(__FUNCTION__);};
  };
//+------------------------------------------------------------------+
class B : public A
  {
public:
                     B(void){};
                    ~B(void){};
   virtual void       func(){Print(__FUNCTION__);};
   void              func1(){A::func();};
  };
//+------------------------------------------------------------------+
void OnStart()
  {
   A *obj=new B();
   obj.func();
   obj.func1();
   delete obj;
  }
//+------------------------------------------------------------------+


o_o
Модератор
23689
o_o 2012.01.09 19:50  

да, так, virtual только добавить все же надо.


и тут даже далеко ходить не надо. Посмотри в стандартную библиотеку. Таких вызово не мало. Например

void CExpert::Magic(ulong value)
  {
   if(m_trade!=NULL)    m_trade.SetExpertMagicNumber(value);
   if(m_signal!=NULL)   m_signal.Magic(value);
   if(m_money!=NULL)    m_money.Magic(value);
   if(m_trailing!=NULL) m_trailing.Magic(value);
//---
   CExpertBase::Magic(value);
  }

//--------------------------------
bool CExpert::ValidationSettings()
  {
   if(!CExpertBase::ValidationSettings()) return(false);
//--- Check signal parameters
   if(!m_signal.ValidationSettings())
     {


в основном такие вызовы применяются в момент инициализации потомка.
Например в родителе инициализируются его параметры, а в потомке дополнительные. Но имя у функции будет одно и то же типа Init(параметры).

Nikolay Demko
12462
Nikolay Demko 2012.01.09 20:01  
sergeev:

да, так, virtual только добавить все же надо.


и тут даже далеко ходить не надо. Посмотри в стандартную библиотеку. Таких вызово не мало. Например


в основном такие вызовы применяются в момент инициализации потомка.
Например в родителе инициализируются его параметры, а в потомке дополнительные. Но имя у функции будет одно и то же типа Init(параметры).

Ясно, те подобный приём можно применять когда у потомков имеется общая начальная часть различных реализаций, тогда просто общую для всех часть виртуалят в предке и вызывают внутри функции потомка.
o_o
Модератор
23689
o_o 2012.01.09 20:06  

да, думаю что 90% потребностей так и делается. Наверно бывают очень редкие исключения, когда потомок перепрыгивает через свою переопределенную функцию и вызывает функцию родителя.

Документация по MQL5: Основы языка / Функции / Вызов функции
Документация по MQL5: Основы языка / Функции / Вызов функции
  • www.mql5.com
Основы языка / Функции / Вызов функции - Документация по MQL5
123
Авторизуйтесь или зарегистрируйтесь, чтобы добавить комментарий