Download MetaTrader 5

OOP - calling the constructor from within another method?

To add comments, please log in or register
Do you want to write a technical indicator? Find solution in MQL5 Reference!
Carl Schreiber
6591
Carl Schreiber 2016.09.20 19:09 

Hi,

My aim:

One base class with its constructor and several different derived classes with different parameters using the one constructor of the base class.

The default approach would be a

  1. A constructor of the derived classed that references to the base class
  2. A different method setParas2(..) that sets the individual parameters (objects) of its class.

This is realized by class TestDerv1 the constructor and the method setParas2(..).

But now I'd like to do both: the constructor and the method setParas2(..) in one method setParas1(..) which returns the reference of the constructed instance and which would enable me to call only 1 method!!

This is realized in the attached script - but with two compiler errors that I'd like to get rid off - if I would know how!!
#property strict
//+------------------------------------------------------------------+
//| Script program start function                                    |
//+------------------------------------------------------------------+

#include <Object.mqh>
class TestCL {
private:
         int m_id;
         double m_a[];
public:
         TestCL(const int id, const int sz); // constructor  
        ~TestCL() {};                        //  destructor  
};
TestCL::TestCL(const int id, const int sz) {
   m_id = id;
   ArrayResize(m_a,sz);
};

class TestDerv1 : public TestCL {
private:
         int      m_id;
         double   m_a[];
         double   m_coeff1,m_coeff2;
         int      m_int0;
         string   m_name;
public:
                  TestDerv1(const int id, const int sz) : TestCL(id,sz) {};   // constructor  
                 ~TestDerv1(){};                                              //  destructor
      TestDerv1*  setParas1( const int id, const int sz,
                             const string name, const double c1, const double c2, const int i0);
         int      setParas2( const string name, const double c1, const double c2, const int i0);
};
// construction an setup in 2 steps
int TestDerv1::setParas2( const string name, const double c1, const double c2, const int i0) {
      m_coeff1 = c1;
      m_coeff2 = c2;
      m_int0 = i0;
      m_name = name;
      if (ArraySize(m_a)>i0) ArrayResize(m_a,i0);
      return(i0);                          
}
// construction and setup in one step:
TestDerv1* TestDerv1::setParas1( const int id, const int sz, const string name, const double c1, const double c2, const int i0) {
      TestDerv1* ret;
      ret = new TestDerv1(id,fmax(sz,i0));
      m_coeff1 = c1;
      m_coeff2 = c2;
      m_int0 = i0;
      m_name = name;
      return(ret);                          
}

// Script
void OnStart() {
   TestCL*  cl1 = TestDerv1::setParas1( 1,12,  "Test 1", 3.1416, 2.718281828459, 99);  // line 63 error 1
   TestCL*  cl2 = new TestDerv1(2,12);                                                 // line 64
   cl2.setParas2( "Test 2", 3.1416, 2.718281828459, 99 );                              // line 65 error 2
}

Unfortunately this causes two compiler errors:

'setParas1' - access to non-static member or function   testClass01.mq4 63      30
'setParas2' - member function not defined       testClass01.mq4         65      8

So how do I call in line 63 a method of a class that is not yet created?

Why do I get in line 65 the function not defined message?

Thanks in advance!!

Files:
Blahtech Limited
3599
James Cater 2016.09.20 20:07  

There were so many things that didn't sit right, so I spent a few mins putting together a more natural version.

#property strict

//#include <Object.mqh>

class TestCL {
protected:
   int m_id;
   double m_a[];
   
public:
   TestCL(int id, int sz);
};

TestCL::TestCL(int id, int sz) :
   m_id(id)
{
   ArrayResize(m_a, sz);
};


class TestDerv1 : public TestCL {
private:
   string  m_name;
   double  m_coeff1;
   double  m_coeff2;
   int     m_int0;
   
public:
   TestDerv1(int id, int sz) : TestCL(id,sz) {};
   TestDerv1(int id, int sz, string name, double c1, double c2, int i0);
              
   void setParas2(string name, double c1, double c2, int i0);
};

// construction and setup in one step
TestDerv1::TestDerv1(int id, int sz, string name, double c1, double c2, int i0) :
   TestCL(id, fmax(sz, i0)),
   m_name(name),
   m_coeff1(c1),
   m_coeff2(c2),
   m_int0(i0)
{
}

// construction an setup in 2 steps
void TestDerv1::setParas2(string name, double c1, double c2, int i0)
{
   if (ArraySize(m_a) > i0)
   {
      ArrayResize(m_a, i0);
   }
   m_name = name;
   m_coeff1 = c1;
   m_coeff2 = c2;
   m_int0 = i0;
}

// Script
void OnStart() {
   TestCL*    cl1 = new TestDerv1(1, 12, "Test 1", 3.1416, 2.718281828459, 99);
   TestDerv1* cl2 = new TestDerv1(2, 12);
   
   cl2.setParas2("Test 2", 3.1416, 2.718281828459, 99);
}
Carl Schreiber
6591
Carl Schreiber 2016.09.20 22:08  
James Cater:

There were so many things that didn't sit right, so I spent a few mins putting together a more natural version.

Thank you. But your solution of
TestDerv1(int id, int sz, string name, double c1, double c2, int i0);

means that I can't/don't use the constructor of the base class it is overriding the construction method - ok that works!

But I want to use the later may be a lot more complex constructor of the base class (which I do not want to re-write or copy ' paste) in combination with the individual part of the derived class.

I can write as well a simple non-OOP function and within it creates a new instance and than it sets its individual parameter - but that is not OOP.

Blahtech Limited
3599
James Cater 2016.09.21 01:47  
Carl Schreiber:
Thank you. But your solution of

means that I can't/don't use the constructor of the base class it is overriding the construction method - ok that works!

But I want to use the later may be a lot more complex constructor of the base class (which I do not want to re-write or copy ' paste) in combination with the individual part of the derived class.

I can write as well a simple non-OOP function and within it creates a new instance and than it sets its individual parameter - but that is not OOP.

TestDerv1::TestDerv1(int id, int sz, string name, double c1, double c2, int i0) :

   TestCL(id, fmax(sz, i0)),  //   <<< This is calling the Constructor of the base class

   m_name(name),
   m_coeff1(c1),
   m_coeff2(c2),
   m_int0(i0)
{
}

The solution above does call the constructor of the base class. If you wish to make the base class constructor more complex you just expand the derived class constructor args and pass them through

TestDerv1::TestDerv1(int id, int sz, int extra1, double extra2, double extra3, string name, double c1, double c2, int i0) :

   TestCL(id, fmax(sz, i0), extra1, extra2, extra3), // Extra args passed through to more complex base constructor

   m_name(name),
   m_coeff1(c1),
   m_coeff2(c2),
   m_int0(i0)
{
}

If this is not what you mean then sorry I really don't understand what you are trying to achieve.

Carl Schreiber
6591
Carl Schreiber 2016.09.21 08:11  

My problem is systematically!

Theses Parameters ( int id, int sz ) are for all derived classes the same and should be treated by the constructor of the base method. Just assume that theses are not the only one and it will do a lot more than setting an object and sizing an array - this is just an example. Therefore I want to define the constructor of of the derived class TestDerv1 by the use of the base class TestCL:

TestDerv1(int id, int sz) : TestCL(id,sz) {};

The second method with (string name, double c1, double c2, int i0 ) is individual for any derived class. It has to be written for any of them.

One solution to solve the problem is to write for all individual derived classes their individual constructor or as I said to write a non-OOP function that does the trick.

But I would like to know whether and how I can realize my OOP idea - or why it is not possible. It can be that C++ might be able to do the trick but MQL4/5 can't.

Carl Schreiber
6591
Carl Schreiber 2016.09.21 08:47  
May be what I want cannot be realized as there is no created instance to which the method can be applied to.
To add comments, please log in or register