Download MetaTrader 5

class FruitClass (SOLVED)

To add comments, please log in or register
GrumpyDuckMan
564
GrumpyDuckMan  

Hello everyone,

I am not sure how to ask this question, but I give it ago anyway.

The value of the first variable changes every time that FruitClass is called (excuse me if that the incorrect terminology).

Now as for the rest of the variables stay the same values until they are given a specified value. What is the reason for this?



class FruitClass
  {

protected:
   int               Apple;   // 145947472: changes
   int               Lemon;   // 92472248: stays the same
   int               Pear;    // 0: stays the same
   int               Bananna; // 0: stays the same 
public:
   int               Onion;   // 28: stays the same

   void              FruitClass(void);
  };
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
FruitClass::FruitClass(void)
  {
  Apple=1;
  Lemon=4;
  Pear=5;
  Bananna=3;
  Onion=12;

  }
nicholishen
1345
nicholishen  
GrumpyDuckMan:

Hello everyone,

I am not sure how to ask this question, but I give it ago anyway.

The value of the first variable changes every time that FruitClass is called (excuse me if that the incorrect terminology).

Now as for the rest of the variables stay the same values until they are given a specified value. What is the reason for this?




Because the computer assigns it to a memory address that could have garbage in it, but in this case you improperly defined the constructor by adding "void" as it's return type. Contructors do not have a return. In order to avoid these issues make sure your constructor doesn't have a return type and it's also more efficient to initialize your member variables with an initialization list. 

class FruitClass
{
protected:
   int               m_apple;       //member variables begin with "m_"
   int               m_lemon;   
   int               m_pear;    
   int               m_bananna; 
public:
                     FruitClass();  //! Constructor does not have a return type
   int               onion;         // public members lowercase
   int               Apple() const; // Methods are capitalized
};
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+

FruitClass::FruitClass(void): m_apple(1),
                              m_lemon(4),
                              m_pear(5),
                              m_bananna(3),
                              onion(12)
{

}
//+------------------------------------------------------------------+
int FruitClass::Apple(void) const //<-- this "const" means that this method cannot change any member variables.
{
   return m_apple;
}
http://www.learncpp.com/cpp-tutorial/8-5a-constructor-member-initializer-lists/
8.5a — Constructor member initializer lists
8.5a — Constructor member initializer lists
  • www.learncpp.com
In the previous lesson, for simplicity, we initialized our class member data in the constructor using the assignment operator. For example: [crayon-5995e9a355750458620021/] When the class’s c…
Mohammad Hossein Sadeghi
2060
Mohammad Hossein Sadeghi  
nicholishen:

Because the computer assigns it to a memory address that could have garbage in it, but in this case you improperly defined the constructor by adding "void" as it's return type. Contructors do not have a return. In order to avoid these issues make sure your constructor doesn't have a return type and it's also more efficient to initialize your member variables with an initialization list. 

http://www.learncpp.com/cpp-tutorial/8-5a-constructor-member-initializer-lists/

Useful instruction.

Mohammad Hossein Sadeghi
2060
Mohammad Hossein Sadeghi  
GrumpyDuckMan:

Hello everyone,

I am not sure how to ask this question, but I give it ago anyway.

The value of the first variable changes every time that FruitClass is called (excuse me if that the incorrect terminology).

Now as for the rest of the variables stay the same values until they are given a specified value. What is the reason for this?




Constructors are to be called once. Subsequent calls doesn't make sense.

GrumpyDuckMan
564
GrumpyDuckMan  
nicholishen:

Because the computer assigns it to a memory address that could have garbage in it, but in this case you improperly defined the constructor by adding "void" as it's return type. Contructors do not have a return. In order to avoid these issues make sure your constructor doesn't have a return type and it's also more efficient to initialize your member variables with an initialization list. 

http://www.learncpp.com/cpp-tutorial/8-5a-constructor-member-initializer-lists/

Hello nicholishen,


Thank you for clearing that up for me,  also thanks a lot for the great link.

Stuart Browne
6875
Stuart Browne  
GrumpyDuckMan:

Hello nicholishen,


Thank you for clearing that up for me,  also thanks a lot for the great link.


I'll 2nd that, fantastic resource.

JC
1577
JC  
Stuart Browne:

I'll 2nd that, fantastic resource.

Great resource but... any C++ material needs to be take with a tiny pinch of salt when applying it to MQL4/5.

Strictly speaking, there's no reason why MQL4/5 should choose to follow this or any other C++ standard; there's no reason why MQL4/5 shouldn't initialise these member variables to zero. And there are some instances where MQL4/5 diverges from the equivalent C++ standard. For example:

#property strict

int ExampleGlobalVariable;

void OnInit()
{
   Print("Value!  : ", ExampleGlobalVariable);
}  

void OnTick() {}

In C/C++, such a global variable is always initialized to zero. In MT4, I've similarly never seen it not get initialized to zero. But in MT5 I have seen very occasional instances where, repeatably, such a global variable is not initialized to zero.

Therefore, exercise a little bit of caution when applying C++ documentation to MQL4/5...

GrumpyDuckMan
564
GrumpyDuckMan  
Mohammad Hossein Sadeghi:

Constructors are to be called once. Subsequent calls doesn't make sense.

Hello Mohammad,

For a couple of months now, I have been trying to test my ability understanding MQL4 programming and fixing coding issues.  I trying to involve program flow, application use, concepts, methods, etc.

I'm still learning the basics, I already worked out that classes are very different in many ways. I still want to work with classes at the moment, I don't believe that I am comfortable in using them yet. 

whroeder1
16764
whroeder1  

JC: there's no reason why MQL4/5 shouldn't initialise these member variables to zero.

C/C++, such a global variable is always initialized to zero. In MT4, I've similarly never seen it not get initialized to zero. But in MT5 I have seen very occasional instances where, repeatably, such a global variable is not initialized to zero.

Using Program Properties (#property) - Preprocessor - Language Basics - MQL4 Reference strict or not changes this behavior. Updated MQL4 - MQL4 Reference

With strict, the program follows C/C++ standard: local variables are not initialized. @JC your link specifically says

Non-static variables (local variables) are indeterminate. Reading them prior to assigning a value results in undefined behavior.
You've got it backwards.
nicholishen
1345
nicholishen  
GrumpyDuckMan:

Hello Mohammad,

For a couple of months now, I have been trying to test my ability understanding MQL4 programming and fixing coding issues.  I trying to involve program flow, application use, concepts, methods, etc.

I'm still learning the basics, I already worked out that classes are very different in many ways. I still want to work with classes at the moment, I don't believe that I am comfortable in using them yet. 


Don't let it overwhelm you... start out making simple classes that print to the log - and then as you learn you can start applying inheritance to make them more robust.

For example: 

#include <Object.mqh>

class SymbolBase : public CObject
{
protected:
   string         m_symbol;
public:
                  SymbolBase(const string symbol):m_symbol(symbol){}
   string         Symbol()    const { return m_symbol ;}
};

void OnStart()
{
   SymbolBase symbol(_Symbol);
   Print("symbol.Symbol() = ",symbol.Symbol());
}

...and then you can derive new class to extend the functionality...

class SymbolPriceCurrent : public SymbolBase
{
public:
                  SymbolPriceCurrent(const string symbol):SymbolBase(symbol){}
   double         Bid()       const { return SymbolInfoDouble(m_symbol,SYMBOL_BID); }
   double         Ask()       const { return SymbolInfoDouble(m_symbol,SYMBOL_ASK); }
};

...and even more...

class SymbolPriceAll : public SymbolPriceCurrent
{
protected:
   int            m_period;
   MqlRates       m_rates[];
public:
                  SymbolPriceAll(const string symbol,const int period);
   double         Open(const int index)const;
   //double         High(const int index)const;
   //double         Low(const int index)const;
   //double         Close(const int index)const;
   int            Refresh();
   int            Total() const { return ArraySize(m_rates); }
protected:
   bool           IsInRange(const int index)const;
};

SymbolPriceAll::SymbolPriceAll(const string symbol,const int period):SymbolPriceCurrent(symbol),
                                                                     m_period(period)
{
   ArraySetAsSeries(m_rates,true);
   Refresh();
}

int SymbolPriceAll::Refresh(void)
{
   return CopyRates(m_symbol,(ENUM_TIMEFRAMES)m_period,0,Bars(m_symbol,m_period),m_rates);
}

double SymbolPriceAll::Open(const int index)const
{
   if(!IsInRange(index))
      return 0.0;
   return m_rates[index].open;
}

bool SymbolPriceAll::IsInRange(const int index)const
{
   return (index >= 0 && index < Total());
}
//+------------------------------------------------------------------+
JC
1577
JC  
whroeder1:

You've got it backwards.

I haven't got anything backwards. I'm not the author of the piece linked to at stackoverflow.com.

What I am saying is the following:

  • With #property strict, global variables are always initialized to zero in MQL4 in all instances I have seen, but I have MQL5 code where this is not the case.
  • There is no reason why MQL4/5 should necessarily choose to follow the C++ standard; it doesn't do so in all cases; and learning MQL4/5 from C++ resources such as www.learncpp.com, above, could potentially be misleading.

I have nowhere said that MQL4 initialises local or member variables when #property strict is defined. I am saying that MQL4/5 is not C++, and could [choose|have chosen] to diverge from the C++ standard in this area.

To add comments, please log in or register