How to pass array of object as a reference parameter

 

Hi all:

 

I create a class and want to pass an array of that class as a reference parameter, however, some error shows: "Structure have objects and cannot be copied". The error occurs at the last line of the function "TradeDataBase".

 In essence, I want to  create a class to store the history order information, save it to the file and read the historical order from file to compile a more comprehensive trade history report. For example, read history orders from several test result files.

 I create a class called YYH_TradeInfo. A function which read the history order from a CSV file and fill all the history orders to the array of class YYH_TradeInfo. The array is pass as reference as "void TradeDataBase(string sFileName, YYH_TradeInfo& cDB[])" .

Call the TradeDataBase from OnTester or other functions from script code.

 Here is my code:

class YYH_TradeInfo
{
public:
   int nTicket;
   string sSymbol;
   double dOpenPrice;
   datetime dtOpenTime;
   double dClosePrice;
   datetime dtCloseTime;
   double dProfit;
   string sComment;
   int nMagicNo;
   
public:
   void YYH_TradeInfo(){};
   void WriteToFile(int nFile);   
   static void WriteFileHeader(int nFile);
   void Init(int nTicketNo);
   void ReadFromFile(int nFile);
};

void TradeDataBase(string sFileName, YYH_TradeInfo& cDB[])
//void TradeDataBase(string sFileName, double& cDB[])
{      
   int nFile = FileOpen(sFileName, FILE_CSV | FILE_READ, ",");
   if (nFile < 0)
   {
      Print("File ", sFileName, " Open Error code=", GetLastError());
      return;
   }
   int nCount = ArraySize(cDB);
   while(!FileIsEnding(nFile) )
   {      
      ArrayResize(cDB, (nCount+1)*sizeof(YYH_TradeInfo));
      YYH_TradeInfo cTrade();
      cTrade.ReadFromFile(nFile);      
      cDB[nCount] = cTrade; 
   }   
}

void OnTester()
{
  YYH_TradeInfo* cTrade[];
  TradeDataBase("history.csv",cDB);   
}
 

You need to pass the classes as pointers,

YYH_TradeInfo * cDB[]
 
wqking:

You need to pass the classes as pointers,

Do you mean modify void TradeDataBase(string sFileName, YYH_TradeInfo& cDB[]) ==> void TradeDataBase(string sFileName, YYH_TradeInfo* cDB[])??

 

I tried that and it doesn't work. 

 
class A {};

void test(A * & a[])
{
}

int OnInit()
{
        A * x[];
        ArrayResize(x, 2);
        x[0] = new A();
        x[1] = new A();
        test(x);

        return(INIT_SUCCEEDED);
}

 
  1. wqking: You need to pass the classes as pointers,
    void TradeDataBase(string sFileName, YYH_TradeInfo& cDB[])   // ok
                                         YYH_TradeInfo* cDB[])   // wrong
                                         YYH_TradeInfo& *cDB[])  // an array of pointers.
    No you do not; you can pass a class as a reference. You must pass arrays (of any type) by reference. You can also pass a pointer as a reference (type& *v) thus returning a pointer.
    A reference to a class and a pointer to a class are identical except the reference must be a real class but the pointer can be to NULL.

  2.      ArrayResize(cDB, (nCount+1)*sizeof(YYH_TradeInfo));
    This is wrong; it's C code. In MT4 you resize to the number of elements not the number of bytes.
  3. asuralm: I create a class and want to pass an array of that class as a reference parameter, however, some error shows: "Structure have objects and cannot be copied".
    • To create an array of a class the class must have a default constructor; this you have.
      public:
         void YYH_TradeInfo(){};                              // Ctor
    • To copy a class you must have a assignment operator.
           cTrade.ReadFromFile(nFile);      
            cDB[nCount] = cTrade;        // Assignment operator required here.
      The alternative would be to drop the temporary
            cDB[nCount].ReadFromFile(nFile);      // No assignment
      

      public:
         YYH_TradeInfo* operator=(const YYH_TradeInfo& that){ // Assignment
         this.nTicket     = that.nTicket;
         this.sSymbol     = that.sSymbol;
         this.dOpenPrice  = that.dOpenPrice;
         this.dtOpenTime  = that.dtOpenTime;
         this.dClosePrice = that.dClosePrice;
         this.dtCloseTime = that.dtCloseTime;
         this.dProfit     = that.dProfit;
         this.sComment    = that.sComment;
         this.nMagicNo    = that.nMagicNo;
         return GetPointer(this);
      }
      The "this." is optional. I always return the pointer (in copy constructor, assignment and set methods) to allow chaining:
      Type exist, v1 v2;        // Type is a class or struct
      
      Type tmp(exist).Method(); // Equivalent to tmp(exist); tmp.Method();
      
      v1 = v2 = exist;          // Equivalent to v2 = exist; v1 = v2;
      
      v1.setA(a).setB(b);       // Equivalent to v1.setA(a); v1.setB(b);
      If you are going to have a assignment you should also have a copy constructor so you can do this
      YYH_TradeInfo existingVariable;
      :
      YYH_TradeInfo newVariable(oldVariable);  // copy construction
      
      YYH_TradeInfo newVariable = oldVariable; // copy construction
      
      YYH_TradeInfo newVariable;               // default construction 
                    newVariable = oldVariable; // and assignment (two calls; inefficient.)
      
      public:
         YYH_TradeInfo* YYH_TradeInfo(const YYH_TradeInfo& that) // Copy
         : nTicket(that.nTicket)
         , sSymbol(that.sSymbol)
         , dOpenPrice(that.dOpenPrice)
         , dtOpenTime(that.dtOpenTime)
         , dClosePrice(that.dClosePrice)
         , dtCloseTime(that.dtCloseTime)
         , dProfit(that.dProfit)
         , sComment(that.sComment)
         , nMagicNo(that.nMagicNo)
         {}
         return GetPointer(this);
      }
      
  4. After you resize to nCount+1 and then set cDB[nCount] you must increment nCount.
 

cDB[nCount] = cTrade; // this statements is not an assignment, but rather a copy statement. 

 You cannot have strings (as well as objects, dynamic arrays) in a structure/object you like to copy to an array element of fixed size.

Use a struct with fixed length (replace strings by char[12] or so) and write it to a file.

 
WHRoeder:
  1. wqking: You need to pass the classes as pointers,
    No you do not; you can pass a class as a reference. You must pass arrays (of any type) by reference. You can also pass a pointer as a reference (type& *v) thus returning a pointer.
    A reference to a class and a pointer to a class are identical except the reference must be a real class but the pointer can be to NULL.

  2. This is wrong; it's C code. In MT4 you resize to the number of elements not the number of bytes.
  3. asuralm: I create a class and want to pass an array of that class as a reference parameter, however, some error shows: "Structure have objects and cannot be copied".
    • To create an array of a class the class must have a default constructor; this you have.
    • To copy a class you must have a assignment operator.The "this." is optional. I always return the pointer to allow chaining: assignments {v1 = v2 = v3;} and set methods {v.setA(a).setB(b);}
    • The alternative would be to drop the temporary
  4. After you resize to nCount+1 and then set cDB[nCount] you must increment nCount.

Thanks for your help. Problem solved.

  

 
Ovo: cDB[nCount] = cTrade; // this statements is not an assignment, but rather a copy statement.

That is an assignment as opposed to a copy constructors. Type v = v1 is a copy constructor, i.e. create a new v from v1.