Accessing child function from base class

Mohd Syafiq Johar Arrifin
337

It is possible for base class execute function on child class?


Example:

I have base class as shown below. The constructor only execute update() function. And the update() function must execute the function that has on it child class

// Base.mqh

class CBase {
        private:
        protected:
                int mData;
        public:
                CBase () { mData = 1; update(); }
                ~CBase () { return; }

                void update();
}

CBase::update() {
        // Execute update from child class
        CChild.update()  // This only abstract
}


And the child class look like this:

// Child.mqh

class CChild : protected CBase {
        private:
        protected:
        public:
                CChild () { }
                ~CChild () { return; }

                void update();
}

void CChild::update() {
        Alert(mData);
}


As we can see in base class I have put CChild.update(). But that never work. What is the correct way to calling it.


Also if possible, suggest a best practice code style for above example


Thank you

Dominik Christian Egert
2729
You cannot call a derived function from within a base class.

You need to use polymorphism. Outside your class, in your other code, you create a pointer variable of type base class and assign it a pointer to the derived class object. Then you call the pointers function "update" from the base class objects pointer. Since it is a derived object, the update function of the derived object gets called.

That is polymorphism.
Mohd Syafiq Johar Arrifin
337
Dominik Christian Egert #:
You cannot call a derived function from within a base class.

You need to use polymorphism. Outside your class, in your other code, you create a pointer variable of type base class and assign it a pointer to the derived class object. Then you call the pointers function "update" from the base class objects pointer. Since it is a derived object, the update function of the derived object gets called.

That is polymorphism.


From what I understand, you propose like this:

- Outside your class, in your other code, you create a pointer variable of type base class and assign it a pointer to the derived class object.

// Child.mqh

class CChild : protected CBase {
        private:
        protected:
        public:
                CChild () { }
                ~CChild () { return; }

                void update();
}

void CChild::update() {
        Alert(mData);
}


CBase *child = new CChild();


- Then you call the pointers function "update" from the base class objects pointer. Since it is a derived object, the update function of the derived object gets called

// Base.mqh

class CBase {
        private:
        protected:
                int mData;
        public:
                CBase () { mData = 1; update(); }
                ~CBase () { return; }

                void update();
}

CBase::update() {
        child.update();
}


After tried the above method, I get error:

conversion from 'CChild *' to 'CBase *' is not accessible because of inheritance access

Dominik Christian Egert
2729
Mohd Syafiq Johar Arrifin #:


From what I understand, you propose like this:

- Outside your class, in your other code, you create a pointer variable of type base class and assign it a pointer to the derived class object.


- Then you call the pointers function "update" from the base class objects pointer. Since it is a derived object, the update function of the derived object gets called


After tried the above method, I get error:

conversion from 'CChild *' to 'CBase *' is not accessible because of inheritance access


Almost got it. But you cannot call the child function from inside the base class.

It is necessary to call the function from outside.

IE in OnInit, you use the base class pointer, pointing to the child class and call the update function.

But, your base class must provide an Update-function as well, although it can be declared fully virtual.

It will be overwritten by the child class function, this is done in runtime, so you could have multiple, differing child classes assigned to the base class pointer variable, and still get the correct update function called on every child object.



William Roeder
28365
William Roeder  
Mohd Syafiq Johar Arrifin: It is possible for base class execute function on child class?

Make the method virtual in the base class and call it.

R4tna C
432
R4tna C  
Mohd Syafiq Johar Arrifin #:


conversion from 'CChild *' to 'CBase *' is not accessible because of inheritance access


Instead of instantiating from the base class and creating a pointer to the child class, why not just instantiate the child class?

I mean:

CChild child;

Instead of:

CBase *child = new CChild();

 Maybe your goal is something else, but I played around with your code and could get a basic working version 

Samuel Manoel De Souza
11410
The method has to be virtual in both classes

    virtual void       update();
Documentation on MQL5: Language Basics / Object-Oriented Programming / Virtual Functions
Documentation on MQL5: Language Basics / Object-Oriented Programming / Virtual Functions
  • www.mql5.com
Virtual Functions - Object-Oriented Programming - Language Basics - MQL5 Reference - Reference on algorithmic/automated trading language for MetaTrader 5
Samuel Manoel De Souza
11410
Dominik Christian Egert #:

Almost got it. But you cannot call the child function from inside the base class.

It is necessary to call the function from outside.

IE in OnInit, you use the base class pointer, pointing to the child class and call the update function.

But, your base class must provide an Update-function as well, although it can be declared fully virtual.

It will be overwritten by the child class function, this is done in runtime, so you could have multiple, differing child classes assigned to the base class pointer variable, and still get the correct update function called on every child object.



He can call Update() from base class since that Update be virtual

Mohd Syafiq Johar Arrifin
337
R4tna C #:

Instead of instantiating from the base class and creating a pointer to the child class, why not just instantiate the child class?

I mean:

Instead of:


 Maybe your goal is something else, but I played around with your code and could get a basic working version 

Thank you R4tna C.

The suggested way actually work. But after a few test, I found it cause buggy & my terminal become unresponsive.


Dominik Christian Egert #:

Almost got it. But you cannot call the child function from inside the base class.

It is necessary to call the function from outside.

IE in OnInit, you use the base class pointer, pointing to the child class and call the update function.

Okey, now I understand what polymorphism is after seeing this documentation.

The polymorphism need an execution script.mq4 to execute it.


The update in base class is rarely called on script or ea, and it's only called once during onInit.

But it called multiple times from base class itself.

// Base.mqh

class CBase {
        private:
        protected:
                int mData;
        public:
                CBase () { mData = 1; update(); }
                ~CBase () { return; }

                void update();
                void Foo1();
                void Foo2();
}

void CBase::update() {
        child.update(); // child class
}

void CBase::Foo1() {
        // do something
        update();       // base class
}


void CBase::Foo2() {
        // do something
        update();       // base class
}


Previously, all the code inside base and child file are in same file

// Base.mqh

class CBase {
        private:
        protected:
                int mData;
        public:
                CBase () { mData = 1; update(); }
                ~CBase () { return; }

                void update();
                void update1();
                void update2();
}

void CBase::update() {
        update1();      // called within the same class
        update2();      // called within the same class
}

void CBase::update1() {
        // do something
}


void CBase::update2() {
        // do something
}

Because of there's too much line of code & the code become unreadable.

I refactored, separate the code into child.


Dominik Christian Egert #:


But, your base class must provide an Update-function as well, although it can be declared fully virtual.

It will be overwritten by the child class function, this is done in runtime, so you could have multiple, differing child classes assigned to the base class pointer variable, and still get the correct update function called on every child object.


William Roeder #:

Make the method virtual in the base class and call it.

I never work with virtual method before. And seeing the documentation, I understand the concept that Dominik Christian Egerts state:  " It will be overwritten by the child class function "


But how to make the virtual method to be called in base class.

Could you provide some code example?

Polymorphism - Object-Oriented Programming - Language Basics - MQL4 Reference
Polymorphism - Object-Oriented Programming - Language Basics - MQL4 Reference
  • docs.mql4.com
Polymorphism - Object-Oriented Programming - Language Basics - MQL4 Reference
R4tna C
432
R4tna C  
Mohd Syafiq Johar Arrifin #:

Thank you R4tna C.

The suggested way actually work. But after a few test, I found it cause buggy & my terminal become unresponsive.

That is a surprise as I use this approach a lot and have not had such issues. Were you by nay chance creating a new object on every tick?

That could consume a lot of memory - I am sure you know already, but it is better to instantiate once and re-use.

Also, what is it you are planning to do with this approach? Seems very involved and intricate

Samuel Manoel De Souza
11410
Mohd Syafiq Johar Arrifin #:

Thank you R4tna C.

The suggested way actually work. But after a few test, I found it cause buggy & my terminal become unresponsive.


Okey, now I understand what polymorphism is after seeing this documentation.

The polymorphism need an execution script.mq4 to execute it.


The update in base class is rarely called on script or ea, and it's only called once during onInit.

But it called multiple times from base class itself.


Previously, all the code inside base and child file are in same file

Because of there's too much line of code & the code become unreadable.

I refactored, separate the code into child.


I never work with virtual method before. And seeing the documentation, I understand the concept that Dominik Christian Egerts state:  " It will be overwritten by the child class function "


But how to make the virtual method to be called in base class.

Could you provide some code example?

Here is the example. and the output.

class Base
  {
public:
                     Base(void) {;}
                    ~Base(void) {;}

   void              CallVirtualMethod(void) {VirtualMethod();}
protected:
   virtual void      VirtualMethod(void) {Print(__FUNCTION__, ", not implement...");}
  };
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
class Chield1: public Base
  {
public:
                     Chield1(void){;}
                    ~Chield1(void){;}
protected:
   virtual void      VirtualMethod(void) {Print(__FUNCTION__, ", Chield1...");}
  };
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
class Chield2: public Base
  {
public:
                     Chield2(void){;}
                    ~Chield2(void){;}
protected:
   virtual void      VirtualMethod(void) {Print(__FUNCTION__, ", Chield2...");}
  };

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void Fun(void)
  {
   Base* pointer;
//---
   pointer = new Base();
   pointer.CallVirtualMethod();
   delete pointer;
//---
   pointer = new Chield1();
   pointer.CallVirtualMethod();
   delete pointer;
//---
   pointer = new Chield2();
   pointer.CallVirtualMethod();
   delete pointer;
  }