Deprecated behavior, hidden method calling will be disabled in a future MQL compiler version

 

I create an inherited class from class CSymbolInfo.

I overwrite the Name(const string name) method, not the Name(void) method.

Than I call the Name(void) method in the script and it says (warning) "deprecated behavior, hidden method calling will be disabled in a future MQL compiler version" at compiling. Why???

#include <Trade\SymbolInfo.mqh>

class CSymInfo : public CSymbolInfo
  {
public:
   bool              Name(const string name) { return(CSymbolInfo::Name(name));  }
  };

void OnStart()
  {
   CSymInfo symbolInfo;
   symbolInfo.Name(_Symbol);
   string name = symbolInfo.Name();
  }


If I add the Name(void) method to the inherited class than compiler doesn't write any warnings.

#include <Trade\SymbolInfo.mqh>

class CSymInfo : public CSymbolInfo
  {
public:
   string            Name(void) const        { return(CSymbolInfo::Name());      }
   bool              Name(const string name) { return(CSymbolInfo::Name(name));  }
  };

void OnStart()
  {
   CSymInfo symbolInfo;
   symbolInfo.Name(_Symbol);
   string name = symbolInfo.Name();
  }

Why the compiler can't use the inherited Name(void) method from the parent class?

 
Petr Nosek:

I create an inherited class from class CSymbolInfo.

I overwrite the Name(const string name) method, not the Name(void) method.

Than I call the Name(void) method in the script and it says (warning) "deprecated behavior, hidden method calling will be disabled in a future MQL compiler version" at compiling. Why???


If I add the Name(void) method to the inherited class than compiler doesn't write any warnings.

Why the compiler can't use the inherited Name(void) method from the parent class?

What you do is not override but hide the Name(const string name) method.

In order to override, you should have "virtual" in both (because only one will hide the other) base Name() methods.

   virtual string            Name(void) const { return(m_name); }
   virtual bool              Name(const string name);

And to ensure you override, it's best practice to add "override" in the inherited class.

To check which Name() is called, run your script and that one and check which method is called:

void OnStart()
  {
   CSymbolInfo *symbolInfo=new CSymInfo();      // base object with inherited pointer
   symbolInfo.Name(_Symbol);
   string name = symbolInfo.Name();
  }
 
Amir Yacoby #:
In order to override, you should have "virtual" in both (because only one will hide the other) base Name() methods.

You cannot change the standard library. If you change <Trade\SymbolInfo.mqh>, the next terminal update will roll back all changes to the standard library files.

Petr Nosek:

I create an inherited class from class CSymbolInfo.

I overwrite the Name(const string name) method, not the Name(void) method.

Than I call the Name(void) method in the script and it says (warning) "deprecated behavior, hidden method calling will be disabled in a future MQL compiler version" at compiling. Why???

If I add the Name(void) method to the inherited class than compiler doesn't write any warnings.

Why the compiler can't use the inherited Name(void) method from the parent class?

Those 2 methods are not virtual in CSymbolInfo, you cannot override them. Trying to overload those methods makes your code ambiguous due to the same signatures. I would either not use the standard library, or at most I would name the methods differently in the derived class.

 

Another solution could be to call Name(void) explicitly (no need to add it in the inherited class):

string name = symbolInfo.CSymbolInfo::Name();

but I prefer your solution because it avoids the downside of changing the parent class in your code if CSymInfo inherits from another class in the future.

 
Vladislav Boyko #:

You cannot change the standard library. If you change <Trade\SymbolInfo.mqh>, the next terminal update will roll back all changes to the standard library files.

Those 2 methods are not virtual in CSymbolInfo, you cannot override them. Trying to overload those methods makes your code ambiguous due to the same signatures. I would either not use the standard library, or at most I would name the methods differently in the derived class.

Sure you can't override, and that's one of the (many) reasons to not use them.. 

 

Also worth noting, hiding and overloading are not the same (and of course both differ from override).

What the Name() in the derived class does to the Name() in the base class, is hiding - not overloading.

Overloading is between methods of the same level, same class - not between derived and base - where the connection is overriding (with virtual in base and override in derived) or hiding.

 
Amir Yacoby #:

Also worth noting, hiding and overloading are not the same (and of course both differ from override).

What the Name() in the derived class does to the Name() in the base class, is hiding - not overloading.

Overloading is between methods of the same level, same class - not between derived and base - where the connection is overriding (with virtual in base and override in derived) or hiding.

In that example, is it also hiding, and not overloading (there are different signatures there)?

[edit]

Vladislav Boyko #:
In that example, is it also hiding, and not overloading (there are different signatures there)?

Short code for that example:

class Rate {
private :
   string    upperBorderName;
   string    lowerBorderName;
   double    getBorder();
   
public :
     // Constructor
    Rate( void );
   // Functies
   int       posPercents( int shift);
};

// Implementatie van de constructor
Rate::Rate() {
};

// Implementatie van functies
double getBorder( string name, int shift){
   return ObjectGetValueByTime ( 0 ,name, iTime ( _Symbol , PERIOD_CURRENT ,shift));
}

int Rate::posPercents( int shift){
   double res     = getBorder(upperBorderName,shift);
   double sup     = getBorder(lowerBorderName,shift);
   return 0;
}

void OnStart() {}
 
Vladislav Boyko #:

In that example, is it also hiding, and not overloading (there are different signatures there)?

[edit]

Short code for that example:

Yes, the global scope function getBorder

double getBorder( string name, int shift)

which is declared outside of class declaration (and without class scope Rate::getBorder) hides the private class method 

double    getBorder()

because hiding works by name alone in MQL5.
They are on different scopes so hiding takes place, and not overloading. 

So, either declare the 

getBorder( string name, int shift)

as a method in the class, and the outcome is overloading the parameterless getBorder, or leave it as is - a global function that hides the class method.

 
Amir Yacoby #:

Yes, the global scope function getBorder

which is declared outside of class declaration (and without class scope Rate::getBorder) hides the private class method 

because hiding works by name alone in MQL5.
They are on different scopes so hiding takes place, and not overloading. 

So, either declare the 

as a method in the class, and the outcome is overloading the parameterless getBorder, or leave it as is - a global function that hides the class method.

If you leave it as is, you can explicitly say you are using the global functions

   double res     = ::getBorder(upperBorderName,shift);
   double sup     = ::getBorder(lowerBorderName,shift);

And you will not get the compile messages.

 
Amir Yacoby #:

Yes, the global scope function getBorder

which is declared outside of class declaration (and without class scope Rate::getBorder) hides the private class method 

because hiding works by name alone in MQL5.
They are on different scopes so hiding takes place, and not overloading. 

So, either declare the 

as a method in the class, and the outcome is overloading the parameterless getBorder, or leave it as is - a global function that hides the class method.


A global function does not hide a class method.

How did you come up with that conclusion?
 
Amir Yacoby #:

What you do is not override but hide the Name(const string name) method.

I understand that by declaring the Name(const string name) method in the derived class I hide the same method in the parent class. But I thought that the Name(void) and Name(const string name) methods are overloaded methods and each has a different signature. If I don't declare Name(void) in the derived class, but only Name(const string name), then when calling Name(void) there is no other Name(void) than the one defined in the base class. So the code should not be ambiguous due to the same signatures. I understand from the documentation https://www.mql5.com/en/docs/basis/oop/overload that the compiler should first look for the Name(void) method in the derived class (it won't find it there), then in the parent class and find it there and use it.

I didn't know that declaring an overloaded Name(const string name) method in a derived class hides not only Name(const string name) in the parent class, but also Name(void) in the parent class. One has to keep learning, but I'm not sure if this is a violation of the polymorphism principle. If anyone has a link (maybe to another programming language, since I couldn't find anything like that with the MQL documentation) where this is explained, I'd be very happy.

Documentation on MQL5: Language Basics / Object-Oriented Programming / Overload
Documentation on MQL5: Language Basics / Object-Oriented Programming / Overload
  • www.mql5.com
Within one class it is possible to define two or more methods that use the same name, but have different numbers of parameters. When this occurs...