In MQL 4, I want to generate this error if my class fails to initialize. Like so:
But this doesn't compile.
Ideally I'd like to let the caller know that this instance generation failed. Like so:
I know I could use SetUserError() but I'd like to use one of the others, and I'd like to let this instantiation fail. How could I achieve that?
You don't have much choice, either you set a status flag in your class, something like
bool m_initialized=(interval>0);
and then check it in the caller.
Or you use a custom error, what is the problem with this one ? What do you mean by "use one of the others" ?
My idea was if I could set _LastError to a system error code I'd get neat error descriptions with
#include <ErrorDescription.mqh> #define LOGERR(a) Print(a," error: ",ErrorDescription(GetLastError())) ... LOGERR("failed to create CClass");
But the ErrorDescription() needs to be extended in order to be able to handle your error
My idea was if I could set _LastError to a system error code I'd get neat error descriptions with
ERR_INVALID_PARAMETER is not a system error in mql4.
void CClass::CClass(int interval) // constructor { if(interval<=0) { SetUserError(ERR_INVALID_FUNCTION_PARAMVALUE); m_interval=WRONG_VALUE; return; } m_interval=interval; }
#define LOGERR(a,e) Print(a," error: ",ErrorDescription(e-ERR_USER_ERROR_FIRST)) CClass *clptr; int OnInit() { clptr=new CClass(Inp_Interval); if(_LastError==ERR_USER_ERROR_FIRST+ERR_INVALID_FUNCTION_PARAMVALUE) { LOGERR("failed to create CClass",GetLastError()); delete clptr; return(INIT_FAILED); } }
ERR_INVALID_PARAMETER is not a system error in mql4.
Right, it's MQL 5, I was looking into the wrong reference manual.
The code looks good to go, thank you and @mladen.
Here's the latest version in case someone's interested:
#include <ErrorDescription.mqh> #define LOGERR(a) Print(a,", error: ",_LastError," ",ErrorDescription(_LastError<ERR_USER_ERROR_FIRST ? _LastError : _LastError-ERR_USER_ERROR_FIRST)) ... void CClass::CClass(int interval) // constructor { ResetLastError(); if(interval<=0) { SetUserError(ERR_INVALID_FUNCTION_PARAMVALUE); m_interval=WRONG_VALUE; return; } m_interval=interval; } CClass *clptr; int OnInit() { clptr=new CClass(Inp_Interval); if(_LastError) { LOGERR("failed to create CClass"); // -> failed to create CClass, error: 69587 Invalid function parameter value delete clptr; return INIT_FAILED; } return INIT_SUCCEEDED; }
ErrorDescription.mqh: (for MQL4, for MQL5 see here https://www.mql5.com/de/code/79)
#import "stdlib.ex4" string ErrorDescription(int error_code); #import

- www.mql5.com
It's better practice to implement an init method on your class instead of trying to use MQL's Error system. It will also allow you the opportunity to create static objects in the global scope and still be able to initialize them later.
class Test { public: bool init(int arg) { if (!(0 < arg && arg < 10)) { Print("Error: failed to init Test with arg=", arg); return false; } return true; } }; Test *g_test_ptr; Test g_test_obj; int OnInit() { g_test_ptr = new Test(); return (g_test_obj.init(3) && g_test_ptr.init(20)) ? INIT_SUCCEEDED : INIT_FAILED; }
It's better practice to implement an init method on your class instead of trying to use MQL's Error system. It will also allow you the opportunity to create static objects in the global scope and still be able to initialize them later.
Good. I have been thinking about that. It's just a few classes at the moment but I'd want to settle with a consistent scheme if it gets more.
Setting error codes and leaving the callstack through repeated returns instead of throwing exceptions is sort of a hassle, but yeah ok, we have to
live with it I guess.
Using an Init() method can hardly be called a better practice. It's very similar to using a custom error, we are remaining with uninitialized or wrong state object.
Of course MQL is not C++ is you have to be creative.

- 2011.02.14
- ThomsonThomson 8,0561515 gold badges6666 silver badges110110 bronze badges
- stackoverflow.com
Using an Init() method can hardly be called a better practice. It's very similar to using a custom error, we are remaining with uninitialized or wrong state object.
Of course MQL is not C++ is you have to be creative.
MQL is nowhere near the sophistication of other languages when it comes to exception handling (there is none). I'd strongly argue that a boolean initialization method is the best way to initialize an object in MQL, and especially since it is the way that almost all MQL library code is written. No need to deviate from MQL design patterns and attempt to use the Error system which only serves to provide logging. Perhaps you could set a user error from an initializer method, but one thing is for certain -- you never want to use the constructor for initialization when anything else relies on a successful instantiation of the object. That's a big MQL no-no.
In MQL 4, I want to generate this error if my class fails to initialize. Like so:
But this doesn't compile.
Ideally I'd like to let the caller know that this instance generation failed. Like so:
I know I could use SetUserError() but I'd like to use one of the others, and I'd like to let this instantiation fail. How could I achieve that?
Use static constructors (another benefit is to give meaningful names to constructors, like the example)
class CAnimal { private: string m_name; int m_age; color m_color; color m_eye_color; protected: static CAnimal *m_instance; CAnimal(const string name,const int age,const color clr,const color eye_color) : m_name(name),m_age(age),m_color(clr),m_eye_color(eye_color){} public: ~CAnimal() { if(CheckPointer(m_instance)==POINTER_DYNAMIC && &this!=m_instance) delete m_instance; } string Name() {return m_name;} int Age() {return m_age;} color Color(){return m_color;} color EyeColor(){return m_eye_color;} virtual void MakeSound()=NULL; }; CAnimal *CAnimal::m_instance=NULL; class CDog : public CAnimal { private: CDog(const string name,const int age,const color clr,const color eye_color) : CAnimal(name,age,clr,eye_color) {} ~CDog() {} public: static CDog *CreateAdultDog(const string name,const int age,const color clr,const color eye_color) { //--- check if(age<2 || clr==clrRed) { Print("Adult dogs should be above 2 years old"); return NULL; } if(clr==clrRed) { Print("Can't create ",name," Dogs can't be red"); return NULL; } m_instance=new CDog(name,age,clr,eye_color); return m_instance; } static CDog *CreateYoungDog(const string name,const int age,const color clr,const color eye_color) { //--- check if(age>=2) { Print("Can't create ",name," Yound dogs should be under 2 years old"); return NULL; } if(clr==clrRed) { Print("Can't create ",name," Dogs can't be red"); return NULL; } m_instance=new CDog(name,age,clr,eye_color); return m_instance; } virtual void MakeSound() { Print("Woof! I am ",Name()," And I am ",Age()<2 ? "a young" : "an adult"," dog"); } }; //+------------------------------------------------------------------+ //| Script program start function | //+------------------------------------------------------------------+ void OnStart() { //--- CAnimal *pluto=CDog::CreateAdultDog("Pluto",3,clrBrown,clrGreen); CAnimal *elton=CDog::CreateYoungDog("Elton",3,clrBlack,clrBrown); CAnimal *reddog=CDog::CreateYoungDog("Sugar",1,clrRed,clrGray); if(CheckPointer(pluto)) { pluto.MakeSound(); delete pluto; } if(CheckPointer(elton)) { elton.MakeSound(); delete elton; } if(CheckPointer(reddog)) { reddog.MakeSound(); delete reddog; } }

- Free trading apps
- Over 8,000 signals for copying
- Economic news for exploring financial markets
You agree to website policy and terms of use
In MQL 4, I want to generate this error if my class fails to initialize. Like so:
But this doesn't compile.
Ideally I'd like to let the caller know that this instance generation failed. Like so:
I know I could use SetUserError() but I'd like to use one of the others, and I'd like to let this instantiation fail. How could I achieve that?