Can't access properties of CObject s stored in global CArrayObj array

 

UPDATE:  Clearly I was overthinking this.  I just created a straight array of CStatuses, figured out how to avoid memory leaks, and I'm good.  Still have a lot of reading up to do on CList usage and understanding proper use of pointers, but I've got what I need apparently working.  Didn't realize global use of custom classes required usage after the class definition in the global scope.  That little bit of ignorance cost me greatly.  Grrrrrr.

Posting my final result as another comment at the end, in case it is useful to someone.

If anyone could advise me if I'm still doing something poorly in my solution, that would be great.  Thanks!

===================================================

Hello and thank you for looking.

I assure you I spend ungodly hours testing, experimenting and researching before resorting to posting here.  My ignorance has me at my wit's end.

I have a global CArrayObj (globalStatusArray) with each elements containing instances of my own custom CObject class with public properties.

In the global scope in the debugger I can see all the objects of the globalStatusArray and all the properties are correctly assigned.  However, I cannot access them.

Of course I would love to directly access them with globalStatusArray[1].m_data.myProperty, but even coding Get(xxx) methods in my class return the wrong values, and instantiating a new class instance with .At(1) returns an instance of my class with all the properties, but their values are gibberish or unititialized or something.

I've tried to detail the code very carefully to make answering this question as easy as possible.

Thank you!


//+------------------------------------------------------------------+
//|                                            expressionTester5.mq5 |
//+------------------------------------------------------------------+
#property copyright ""
#property link      ""
#property version   "1.00"

#include <Arrays\ArrayObj.mqh> 
#include <Arrays\ArrayDouble.mqh>
#include <Arrays\List.mqh>

input ENUM_TIMEFRAMES TF1=PERIOD_MN1;
input ENUM_TIMEFRAMES TF2=PERIOD_W1;
input ENUM_TIMEFRAMES TF3=PERIOD_D1;
input ENUM_TIMEFRAMES TF4=PERIOD_H4;
input ENUM_TIMEFRAMES TF5=PERIOD_H1;
input ENUM_TIMEFRAMES TF6=PERIOD_M15;
input ENUM_TIMEFRAMES TF7=PERIOD_M5;
input ENUM_TIMEFRAMES TF8=PERIOD_M1;



CArrayObj *globalStatusArray=new CArrayObj;
// Currently trying to test if I can use a wrapper class CStatusObjects but
// seems like I can't use ANY of my classes in the global scope, only base classes 
// above works, two below do not
// CStatusObjects *oStatusObjects=new CArrayObj;
//       -- compiler error: 'CStatusObjects' - unexpected token, probably type is missing?      expressionTester5.mq5   27      1
// CStatusObjects *oStatusObjects=new CStatusObjects;
//       -- compiler error: 'CStatusObjects' - unexpected token, probably type is missing?      expressionTester5.mq5   27      1
// 

//+------------------------------------------------------------------+
//| Script program start function                                    |
//+------------------------------------------------------------------+
void OnStart()
  {
   
  InstanciateStatusObjects();
  
  // testing
  CStatuses WTF=*globalStatusArray.At(1);
  int TFNumberTest=WTF.GetTFNumber();
  int histCountTest=WTF.GetHistCount();
  
  Print("TFNumberTest: ",TFNumberTest,"; histCount: ",histCountTest);
  // prints:  2022.05.20 16:41:42.420   expressionTester5 (AUDJPY,H4)   TFNumberTest: 9; histCount: -106054309
  // the incrementer only went from 0-7, there's not a 9 anywhere, and obviously histCount is gibberish
  
  //
  ////// COMMENTS
  // while suspended on above Print() in the debugger I can see globalStatusArray with correct values:
  //  
  //  globalStatusArray   
  //     -> m_data
  //        -> [0]
  //           -> : public CObject
  //              TFNumber          0
  //              timeframe         PERIOD_MN1 (49153)
  //           ... ETC
  //              histCount         0
  //        -> [1]
  //           -> : public CObject
  //              TFNumber          1
  //              timeframe         PERIOD_W1 (32769)
  //              ... ETC
  //              histCount         0
  //
  // but in the WTF array, I see that something is private or out of scope:
  //
  //  WTF
  //     -> m_data
  //        -> [0]
  //           -> : public CObject
  //              TFNumber          9                       // never assigned this value
  //              timeframe         PERIOD_CURRENT (0)     
  //           ... ETC
  //              histCount         -106054309
  //
  //
  //
  //////
  
  
   
   return;
  }
//+------------------------------------------------------------------+


//+------------------------------------------------------------------+
// Instanciate instances of the oStatuses object and load into the 
//+------------------------------------------------------------------+
void InstanciateStatusObjects()
   {  
   ENUM_TIMEFRAMES TFInputs[8];
   TFInputs[0]=TF1;
   TFInputs[1]=TF2;
   TFInputs[2]=TF3;
   TFInputs[3]=TF4;
   TFInputs[4]=TF5;
   TFInputs[5]=TF6;
   TFInputs[6]=TF7;
   TFInputs[7]=TF8;
   
   CArrayObj *statObjArray=new CArrayObj;
   CStatuses *oneStatusObj;
   
   for(int i=0; i<8; i++)
      {
      
      oneStatusObj=new CStatuses;
      oneStatusObj.TFNumber=i;               // in this test, this is being assigned
      oneStatusObj.timeframe=TFInputs[i];    // in this test, this is being assigned
      // just empty values below for now.
      oneStatusObj.label="";
      oneStatusObj.buyOrSell=0;
      oneStatusObj.hasPulledBack=false;
      oneStatusObj.histCount=0;
      oneStatusObj.crossCount=0;
      oneStatusObj.thickOrThin=0;
      oneStatusObj.thickOrThinCurrent=0;
      oneStatusObj.ema6Handle=0;
      oneStatusObj.TMACDHandle=0;
      oneStatusObj.macdPullbackHandle=0;    // in existing code, seems to be redundant usage of the TMACDHandle
      oneStatusObj.TFmsg="";
      oneStatusObj.TFCrossMsg="";
      oneStatusObj.TFstat="";
      oneStatusObj.TFPeriodLabel="";
      
      // add the object to the global array
      globalStatusArray.Add(oneStatusObj);
      
      }
   }


//+------------------------------------------------------------------+


// CLASS DEFINITIONS FOR v2
//+------------------------------------------------------------------+
class CStatuses: public CObject
   {
   public:
         int TFNumber;  // 0-7 corresponding to indicator input parameters
         ENUM_TIMEFRAMES timeframe; 
         string label; 
         int buyOrSell; 
         bool hasPulledBack; 
         int histCount; 
         int crossCount; 
         int thickOrThin;           // consider changing this to "thickOrThinPrior"
         int thickOrThinCurrent;
         // handles required for use
         int ema6Handle;
         int TMACDHandle;
         // can this be the handle stored in a different instance of the class (the one that is the pullback timeframe?)
         // and just use the TMACDHandle stored in the correct class instance?  check the code to see.
         int macdPullbackHandle;          // this does seem to just be a redundant usage of the same handle as TMACDHandle
         // messaging displayed on screen
         string TFmsg;
         string TFCrossMsg;
         string TFstat;
         string TFPeriodLabel;
         
         
   public:
         int GetTFNumber() {return TFNumber;}
         int GetHistCount() {return histCount;}
  
   };


//+------------------------------------------------------------------+
// 
//+------------------------------------------------------------------+
class CStatusObjects: public CArrayObj
   {
   public:
      CStatuses statusObj;
      
   };

Documentation on MQL5: Standard Library / Data Collections / CArrayObj
Documentation on MQL5: Standard Library / Data Collections / CArrayObj
  • www.mql5.com
CArrayObj - Data Collections - Standard Library - MQL5 Reference - Reference on algorithmic/automated trading language for MetaTrader 5
 

Here is what worked for my needs.

//+------------------------------------------------------------------+
//|                                            expressionTester5.mq5 |
//+------------------------------------------------------------------+
#property copyright ""
#property link      ""
#property version   "1.00"

#include <Arrays\ArrayObj.mqh> 
#include <Arrays\ArrayDouble.mqh>
#include <Arrays\List.mqh>

input ENUM_TIMEFRAMES TF1=PERIOD_MN1;
input ENUM_TIMEFRAMES TF2=PERIOD_W1;
input ENUM_TIMEFRAMES TF3=PERIOD_D1;
input ENUM_TIMEFRAMES TF4=PERIOD_H4;
input ENUM_TIMEFRAMES TF5=PERIOD_H1;
input ENUM_TIMEFRAMES TF6=PERIOD_M15;
input ENUM_TIMEFRAMES TF7=PERIOD_M5;
input ENUM_TIMEFRAMES TF8=PERIOD_M1;


//+------------------------------------------------------------------+
//| Script program start function                                    |
//+------------------------------------------------------------------+
void OnStart()
   {
   InstanciateStatusObjects();
   
   //Print("statuses[1].TFNumber: ",statuses[1].TFNumber);
   return;
   }
//+------------------------------------------------------------------+


//+------------------------------------------------------------------+
// Instanciate instances of the oStatuses object and load into the 
//+------------------------------------------------------------------+
void InstanciateStatusObjects()
   {  
   ENUM_TIMEFRAMES TFInputs[8];
   TFInputs[0]=TF1;
   TFInputs[1]=TF2;
   TFInputs[2]=TF3;
   TFInputs[3]=TF4;
   TFInputs[4]=TF5;
   TFInputs[5]=TF6;
   TFInputs[6]=TF7;
   TFInputs[7]=TF8;
   
   for(int i=0; i<8; i++)
      {
      CStatuses *oneStat;
      oneStat=new CStatuses;
      statuses[i]=oneStat;
      // prevent memory leak
      delete oneStat;
      
      statuses[i].TFNumber=i;               // in this test, this is being assigned
      statuses[i].timeframe=TFInputs[i];    // in this test, this is being assigned
      //// just empty values below for now.
      statuses[i].label="";
      statuses[i].buyOrSell=0;
      statuses[i].hasPulledBack=false;
      statuses[i].histCount=0;
      statuses[i].crossCount=0;
      statuses[i].thickOrThin=0;
      statuses[i].thickOrThinCurrent=0;
      statuses[i].ema6Handle=0;
      statuses[i].TMACDHandle=0;
      statuses[i].macdPullbackHandle=0;    // in existing code, seems to be redundant usage of the TMACDHandle
      statuses[i].TFmsg="";
      statuses[i].TFCrossMsg="";
      statuses[i].TFstat="";
      statuses[i].TFPeriodLabel="";
      
      }
   }


//+------------------------------------------------------------------+

//+------------------------------------------------------------------+
// 



// CLASS DEFINITIONS FOR v2
//+------------------------------------------------------------------+
class CStatuses
   {
   public:
         int TFNumber;  // 0-7 corresponding to indicator input parameters
         ENUM_TIMEFRAMES timeframe; 
         string label; 
         int buyOrSell; 
         bool hasPulledBack; 
         int histCount; 
         int crossCount; 
         int thickOrThin;           // consider changing this to "thickOrThinPrior"
         int thickOrThinCurrent;
         // handles required for use
         int ema6Handle;
         int TMACDHandle;
         // can this be the handle stored in a different instance of the class (the one that is the pullback timeframe?)
         // and just use the TMACDHandle stored in the correct class instance?  check the code to see.
         int macdPullbackHandle;          // this does seem to just be a redundant usage of the same handle as TMACDHandle
         // messaging displayed on screen
         string TFmsg;
         string TFCrossMsg;
         string TFstat;
         string TFPeriodLabel;
         
         
   public:
         // Constructor
         CStatuses() {};
         void CStatuses(CStatuses &statObj)
            {
            }
         // Destructor
         ~CStatuses() {};
   };

CStatuses statuses[8];
Reason: