OOP, creating an instance from within the contructor of another class - how?

 
Hi,

in the class CI the constructor needs to create an instance of another class (CQ) which is forward declared - but this fails :(

The mt4 compiler complains:

'CQ' - struct undefined CI.mqh  105     25
 '=' - type mismatch    CI.mqh  105     19

Cry - why?

class CQ;  // forward declaration
class CI : public CObject {
   public:
      CI::CI(CQ* &q[], const int i); // contructor
...

} 

CI::CI(CQ* &q[], const int i) {  //  constructor
   ...
   int n = ArraySize(q);  // start to create another (new) instance of CQ
   ArrayResize(q,n+1);    // one more
   q[n] = new CQ(i);      // <= 'CQ' - struct undefined CI.mqh  ERROR??
}

The constructor of CQ exists with exactly this parameter (in case the compiler checks the existence of CQ...), but anyway the class CQ is declared (forward) in IC - what do I wrong??

Thanks!

 
Carl Schreiber:

Please, provide more code. You have some errors in omitted part. This compiles:

class CQ;  // forward declaration

class CI //: public CObject
{
   public:
      CI(CQ* &q[], const int id); // contructor

}; 

class CQ
{
  public:
    CQ(int i){};
};

CI::CI(CQ* &q[], const int id)
{
  int i = 0;
  int n = ArraySize(q);  // start to create another (new) instance of CQ
  ArrayResize(q,n+1);    // one more
  q[n] = new CQ(i);      // NO ERROR HERE
}
 
Stanislav Korotky:

Please, provide more code. You have some errors in omitted part. This compiles:

May be it does not compiler here with me because CQ is one file and CI the other file?

// file CI.mqh

class CQ;  // forward declaration
class CI //: public CObject
{
   public:
      CI(CQ* &q[], const int id); // contructor
}; 

CI::CI(CQ* &q[], const int id)
{
  int i = 0;
  int n = ArraySize(q);  // start to create another (new) instance of CQ
  ArrayResize(q,n+1);    // one more
  q[n] = new CQ(i);      // and now??
}
This part was from the other file it is not part of the file for the class CI!!
//file CQ.mqh
class CQ
{
  public:
    CQ(int i){};
};
 
Carl Schreiber:

May be it does not compiler here with me because CQ is one file and CI the other file?

This part was from the other file it is not part of the file for the class CI!!
Where do you include both headers?
 

Anyway try this - it's the complete file:

//+------------------------------------------------------------------+
//|                                                           CI.mqh |
//|                                                             Test |
//|                                              http://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Test"
#property link      "http://www.mql5.com"
#property version   "1.00"
#property strict
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
class CQ;
class CI
  {
private:

public:
                     CI(CQ* &q[], const int id); // contructor
                    ~CI();
  };
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
CI::CI(CQ* &q[], const int id)
{
  int n = ArraySize(q);  // start to create another (new) instance of CQ
  ArrayResize(q,n+1);    // one more
  q[n] = new CQ(id);      // and now??
}
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
CI::~CI()
  {
  }
//+------------------------------------------------------------------+
 
Carl Schreiber:

Anyway try this - it's the complete file:

And where is CQ definition? Where is include?
 

I can't include it as CQ has as well a forward declaration to CI.

As it is not possible for both files to include each other I have to use the forward declaration.

 
Carl Schreiber:

I can't include it as CQ has as well a forward declaration to CI.

As it is not possible for both files to include each other I have to use the forward declaration.

It makes no sense. Forward declaration is intended to break such loops in dependencies. But you need an include anyway. Forward declaration DOES NOT define a class, but tells compiler that you'll include the definition lately.
 
class CQ;  // forward declaration

class CI
{
   public:
      CI(CQ* &q[], const int id); // contructor

}; 

class CQ
{
  private:
    const CI *owner;
    
  public:
    CQ(const CI *o)
    {
      owner = o;
    };
};

CI::CI(CQ* &q[], const int id)
{
  int n = ArraySize(q);  // start to create another (new) instance of CQ
  ArrayResize(q,n+1);    // one more
  q[n] = new CQ(&this);
}
Both classes have references to each other. No problem.
 

ok - thanks!

But I thought it would be a nice feature of OOP to have each class with its library of methods in its own file.

 
Carl Schreiber:

ok - thanks!

But I thought it would be a nice feature of OOP to have each class with its library of methods in its own file.

Sure, it is quite common, in fact Java has it as the mandatory rule for public classes. Though the circular dependencies in your example are not a good example of a public class.

Reason: