I could figure out another workaround that would be
CExpertModelTrailing * m_trail = m_trailing;
but then I would have to add it in every child methods, right? is there another way ?
#include <Expert\ExpertBase.mqh>
#include <Expert\ExpertTrailing.mqh>
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
class CExpert_Tparams
{
public:
int m_TrailingBehaviour;
double m_TrailingActivate_1;
double m_TrailingStop_1;
double m_TrailingStep_1;
void CExpert_Tparams() {}
void ~CExpert_Tparams() {}
};
//existing code
class CExpert : public CExpertBase
{
protected:
// [...] some other code
CExpertTrailing *m_trailing; // trailing stops object
// [...] some other code
virtual bool InitTrailing(CExpertTrailing *trailing = NULL);
};
//+------------------------------------------------------------------+
//| Initialization trailing object |
//+------------------------------------------------------------------+
bool CExpert::InitTrailing(CExpertTrailing *trailing)
{
if(m_trailing != NULL)
delete m_trailing;
//---
if(trailing == NULL)
{
if((m_trailing = new CExpertTrailing) == NULL)
return(false);
}
else
m_trailing = trailing;
//--- initializing trailing object
if(!m_trailing.Init(GetPointer(m_symbol), m_period, m_adjusted_point))
return(false);
m_trailing.EveryTick(m_every_tick);
m_trailing.Magic(m_magic);
//--- ok
return(true);
}
// My code
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
class CExpertModelTrailing : public CExpertTrailing
{
protected:
public:
virtual bool CheckTrailingStopLong(int positionIndex, double &sl, double &tp) { return(false); }
virtual bool CheckTrailingStopShort(int positionIndex, double &sl, double &tp) { return(false); }
// let's say for this example CExpert_Tparams class contains all the trailing parameters given by user input
virtual bool InitTrailingParameters(CExpert_Tparams ¶meters)
{
return false;
}
};
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
class CExpertModel : public CExpert
{
public:
//this has been removed
// CExpertModelTrailing *m_trail;
// [...] some other code
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
bool InitTrailing(CExpert_Tparams ¶meters)
{
int trailingBehaviour = parameters.m_TrailingBehaviour;
switch(trailingBehaviour)
{
case 0 :
m_trailing = new CTrailingNone();
// I would like to be able to use m_trailing = new CTrailingNone();
break;
case 1 :
m_trailing = new CTrailingFixedPips();
break;
// [...] some other code
default:
m_trailing = new CTrailingFixedPips();
break;
}
if(!m_trailing.Init(GetPointer(m_symbol), m_period, m_adjusted_point))
return(false); // launching at some point CExpertBase::Init(CSymbolInfo *symbol,ENUM_TIMEFRAMES period,double point)
// this is where i would like some help:
if(!InitTrailingParameters(parameters))
{
return false;
}
return true;
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
bool InitTrailingParameters(CExpert_Tparams ¶meters)
{
//added
CExpertModelTrailing * m_trail = m_trailing;
//this workaround is working
if(!m_trail.InitTrailingParameters(parameters))
return false;
//this is NOT working as m_trailing is of type CExpertTrailing and doesn't have the child methods defined
//if(!m_trailing.InitTrailingParameters(parameters))
// return false;
return true;
}
};
Anyone has an idea ?
maybe I'm over complicating it and I just have to use
CExpertModelTrailing * m_trail = m_trailing;
?
You removed the pointer variable from the class. So how do you expect to assign to a nonexistent variable.
You don't “just have to use” m_trail. Use the variable m_trailing defined in your base class. You are causing your own problem.
Thank you for your reply. I don't understand quite well when you say "You removed the pointer variable from the class." Would you mind explaining ?
I think maybe I explained wrongly:
The Standard Library's CExpert has a m_trailing variable
CExpertTrailing *m_trailing; // trailing stops object
which is the type of CExpertTrailing.
So it doesn't have the added child methods the user (me) can create in its child (CExpertModelTrailing : public CExpertTrailing)
I could just instantiate the child class to get access to all the methods. But the standard library's automation is instantiating the CExpertTrailing class (with m_trailing varialble)...And we can't modify it because it will be overridden on the next metatrader5 update.
If the child class has a B() method I can't access if by using
double b = m_trailing.B();
but I can if I do
CExpertModelTrailing * m_trail = m_trailing; double b = m_trail.B();
Just thought it wasn't very elegant to do so. Or my coding skills are limited and that's why I am asking for advice.
any thoughts on that ?
well I guess if no one is replying, means that redefining a variable is the only way to access a child method, when accessing the parent objet with
CExpertModelTrailing * m_trail = m_trailing;
double b = m_trail.B();
I'm not sure I understand your question correctly.
I sometimes have a situation where child classes are initialized differently. I did something like this:
class CParent { public: void someMethod() {} }; class CChild1 : public CParent { private: int member; public: void initialize(int a_1) { member = a_1; }; }; class CChild2 : public CParent { private: double member1; double member2; public: void initialize(double a_1, double a_2) { member1 = a_1; member1 = a_2;}; }; CParent* objects[2]; int OnInit() { // Assign a descriptor of created object to the temporary pointer of the child class CChild1* tempPtrChild1 = new CChild1; CChild2* tempPtrChild2 = new CChild2; // Using temporary pointers, call methods of the child class tempPtrChild1.initialize(1); tempPtrChild2.initialize(1.0, 2.0); // This can be done without using dynamic_cast objects[0] = tempPtrChild1; objects[1] = tempPtrChild2; // ------- return(CheckPointer(objects[0]) == POINTER_DYNAMIC && CheckPointer(objects[1]) == POINTER_DYNAMIC ? INIT_SUCCEEDED : INIT_FAILED); } void OnTick() { objects[0].someMethod(); objects[1].someMethod(); }
Code just to demonstrate the idea. Of course, I did not run it and did not test it.
The true question is why do you need to access this child method ?
I would even say why do you need to use inheritance at all ?
Thank you Alain for your reply.
I guess this post is more about good practices than something else.
I created a simple model where my classes inherit the standard library classes. So I can add my own methods without the stress of losing my work where MT5 is updating. Maybe I should not use Inheritance and I'm open to other practice with a simple example if possible. I would be happy to implement it according to my coding skills.
I want to access it because natively what the child method B() is doing is not implemented (that's what usually specialisation classes are doing).
The purpose is also to standardise these specialisations calls (idea of kind of strategy design pattern):
for example through an input parameter, the user can choose the type of trailing he wants, as the standard library is instanciating trailing like this:
//+------------------------------------------------------------------+ //| Initialization trailing object | //+------------------------------------------------------------------+ bool CExpert::InitTrailing(CExpertTrailing *trailing) { if(m_trailing!=NULL) delete m_trailing; //--- if(trailing==NULL) { if((m_trailing=new CExpertTrailing)==NULL) return(false); } else m_trailing=trailing; //--- initializing trailing object if(!m_trailing.Init(GetPointer(m_symbol),m_period,m_adjusted_point)) return(false); m_trailing.EveryTick(m_every_tick); m_trailing.Magic(m_magic); //--- ok return(true); }
I can do something like this:
// CExpert_Tparams is the class where the specific trailing parameters are stored //this code is located in the inherited class of CExpert : CExpertModel. bool InitTrailing(CExpert_Tparams ¶meters) { // [...] some code... ENUM_TRAILING_STRATEGY trailingBehaviour = (ENUM_TRAILING_STRATEGY)parameters.m_TrailingBehaviour; switch(trailingBehaviour) { case TRAILING_STRATEGY_NONE : m_trailing = new CTrailingNone(); break; case TRAILING_STRATEGY_CLASSIC : m_trailing = new CTrailingFixedPips(); break; // [...] some code... // this is an attribute of this CExpertModel Class: CExpertModelTrailing *m_trail; m_trail = m_trailing;
But by doing
m_trail = new CTrailingNone();
so, the already present attribute (and used everywhere in the standard library) m_trailing is not used.
That's why I chose (maybe a mistake) to use
m_trailing = new CTrailingNone(); m_trail = m_trailing; //[...] do some actions
This could be implemented for any type of complete "strategy" calling signals, money management and whatever else that could need a specific class instanciation on the fly, depending on, for example, input parameters.
Open to any suggestion. I guess this is just a lack of mql/C++ coding knowledge...
- Free trading apps
- Over 8,000 signals for copying
- Economic news for exploring financial markets
You agree to website policy and terms of use
Hello,
I am struggling with some OOP coding in MQL5.
1. Besides I am asking myself if I should used the standard library (the expert classes) because I am not seeing many people using them ? Are there recommendations (using DoEasy library or make my own ?) Thanks you for your replies
2. before gettings answers to this 1. , I want to solve some coding issues:
The question is, how can I call Child class methods from a parent perspective? I can't modify the parent class methods or make the attribute virtual as this parent class is part of the mql standard libraries.
I am using the standard libraries (the classes in include/Expert). For my purpose, I extended those classes to add methods inside. I get CExpertModel, and its children (see code below).
Let's consider this: using the expert standard library classes and I would like to, for example, to use the existing m_trailing variable instead of the workaround of creating the m_trail variable, because I also have to rewrite the parent methods that include the m_trailing variable.
May be I can use dynamic_cast or something else, but my skill are limited.
Any advice ? (i've read already post https://www.mql5.com/en/forum/430039 )
here's my code (I simplified it to focus on the issue):
Thank you :)