Changing the access specifier for a virtual function

 

Can I change the access to a base class method by using a different access specifier when overriding the method in a descendant?

class CBase
  {
public:
   virtual void virtualMethod() {};
  };

class CTest final : public CBase
  {
private:
   virtual void virtualMethod() override {};
  };

I want to make sure this is normal practice. I haven't seen similar examples in the documentation, and I don't know any other programming languages

 

I just wanted to hide the overridden methods since they are no longer needed in the public section. And I wasn't going to use a base class pointer.

But out of interest, I tried to call a method moved to a private section using a pointer to the base class. And it worked...

#property strict

class CBase
  {
public:
   virtual void virtualMethod()          { Alert("Base");  };
  };

class CChild final : public CBase
  {
private:
   virtual void virtualMethod() override { Alert("Child"); };
  };

void OnStart()
  {
   CBase *a = new CChild;
   a.virtualMethod(); // Child
   delete a;
  }
 

And it also confuses me that the compiler normally perceives the use of the virtual keyword in a private section. This doesn’t make any sense (as far as I know) because a private method cannot be overridden.

But that's just my interest. First of all, I'm interested in this:

Vladislav Boyko:

Can I change the access to a base class method by using a different access specifier when overriding the method in a descendant?

I want to make sure this is normal practice.


[EDITED]

I just saw an extra semicolon after the body of methods in my code. It's a typo

 
Vladislav Boyko #:

And it also confuses me that the compiler normally perceives the use of the virtual keyword in a private section. This doesn’t make any sense (as far as I know) because a private method cannot be overridden.

But that's just my interest. First of all, I'm interested in this:


[EDITED]

I just saw an extra semicolon after the body of methods in my code. It's a typo

Of course a private method can be overridden.

Yes you can use a different access specifier. It's normal practice.

See : https://stackoverflow.com/questions/2141188/changing-function-access-mode-in-derived-class
Changing Function Access Mode in Derived Class
Changing Function Access Mode in Derived Class
  • 2010.01.26
  • hlx236sk hlx236sk 353 1 1 gold badge 3 3 silver badges 4 4 bronze badges
  • stackoverflow.com
Consider the following snippet: Is this legal C++? "This" being changing the virtual function's access mode in the derived class.
 
Alain Verleyen #:
Of course a private method can be overridden.

It turns out that the virtual specifier makes the method available for overriding in descendants, regardless of the access specifier in the base class.

And from this it follows that declaring a PURE method in the private section is meaningless.


Thank you very much, Alain
 
Vladislav Boyko #:

It turns out that the virtual specifier makes the method available for overriding in descendants, regardless of the access specifier in the base class.

And from this it follows that declaring a PURE method in the private section is meaningless.

Why meaningless ?

It's meaningful on the contrary. If it's an implementation detail it should better be private.

 
Alain Verleyen #:

Why meaningless ?

It's meaningful on the contrary. If it's an implementation detail it should better be private.

This is another typo, sorry. Looks like I should sleep more.

I meant to write the word "protected":

Vladislav Boyko #:

And from this it follows that declaring a PURE method in the private protected section is meaningless.


  1. virtual makes a method available for overriding
  2. PURE method, should be overridden
These 2 points together do what the protected section is designed to do:
MQL5 Reference #:

If the protected keyword is used, hidden data can be accessed also from methods of classes - inheritors of this class.

Therefore, I concluded that placing a pure virtual function in a protected section is pointless

 
Vladislav Boyko #:
Therefore, I concluded that placing a pure virtual function in a protected section is pointless

Unless you plan for the child to call a method that is not yet implemented (will be implemented by the child's child)...

But personally, I would look for a way to avoid such complications😄

 
Vladislav Boyko #:

Unless you plan for the child to call a method that is not yet implemented (will be implemented by the child's child)...

But personally, I would look for a way to avoid such complications😄

Actually, no. In fact that is one of the main advantages of virtual functions.

You can implement a generic function in the base class, something like add(), and this might call a pure virtual function like search(), and the child class implements this function for the specific implementation.

Now you can call add() from the child, being it a function from the base class, and using the search function from the child. All search() being protected.

This is also why you implement (mqls understanding of) interfaces.

It makes totally sense and has actual use case and value.
 
Dominik Egert #:
Actually, no. In fact that is one of the main advantages of virtual functions.

You can implement a generic function in the base class, something like add(), and this might call a pure virtual function like search(), and the child class implements this function for the specific implementation.

Now you can call add() from the child, being it a function from the base class, and using the search function from the child. All search() being protected.

This is also why you implement (mqls understanding of) interfaces.

It makes totally sense and has actual use case and value.

I'm not sure if I understood you correctly.

Here is my attempt to make code according to your example:

class CBase
  {
private:
   virtual int search() = 0; // No need to place PURE function in protected section
public:
   void add()
     {
      //...
      Alert(search());       // Use of search() method
      //...
     }
  };

class CChild_1 : public CBase
  {
private:
   int search() override { return(111); }
  };

class CChild_2 : public CBase
  {
private:
   int search() override { return(222); }
  };

void OnStart()
  {
   CBase *child_1 = new CChild_1;
   CBase *child_2 = new CChild_2;
   child_1.add(); // 111
   child_2.add(); // 222
   delete child_1;
   delete child_2;
  }
 
Vladislav Boyko #:

I'm not sure if I understood you correctly.

Here is my attempt to make code according to your example:

Right. That's exactly one of the use cases, and as I described it.

EDIT:
Protected would be required if you have add() in a class between base and child.
Reason: