Can't access protected functions from derived class

 

I noticed that from a derived class I can't access protected functions of an object from its base class (a pointer to other object), however from the base class I can access private functions of the other object (of the same type), and more strangely, from the derived class I can access and modify protected members from the base class directly, which seems contradictory to me.

class BaseClass
{

   private:

      int privateMember;
      void PrivateFunction() { Print("Call private"); }
        
   protected:
      BaseClass* otherPointer;
        
      int protectedMember;
      void ProtectedFunction() { Print("Call protected"); }
                

   public:
      void SetPointer(BaseClass* pointer) { otherPointer = pointer; }
                
      void PrintValues() { Print("private=", privateMember, "; protected=", protectedMember); }
                
      void Test1();
};

void BaseClass::Test1(void)
{

   Print("--Test 1");
   otherPointer.privateMember = 1;
   otherPointer.PrivateFunction();
}

class InheritClass : public BaseClass
{

   public:
      void Test2();
};

void InheritClass::Test2(void)
{

   Print("--Test 2");
   ProtectedFunction();
   otherPointer.protectedMember = 2;
   //otherPointer.ProtectedFunction(); //'BaseClass::ProtectedFunction' - cannot access protected member function
}

BaseClass base_obj;
InheritClass inherit_obj;

void OnInit()
{
   base_obj.SetPointer(GetPointer(inherit_obj));
   inherit_obj.SetPointer(GetPointer(base_obj));
   
   base_obj.Test1();
   inherit_obj.Test2();
   inherit_obj.Test1();
   
   Print("Base values:");
   base_obj.PrintValues();
   Print("Inherit values:");
   inherit_obj.PrintValues();
}

//RESULT:

//--Test 1
//Call private
//--Test 2
//Call protected
//--Test 1
//Call private
//Base values:
//private=1; protected=2
//Inherit values:
//private=1; protected=0

Is it a bug? Or is it something to be expected and has some reasoning to it (which I'm curious to know I must say)?

 
Vladislav Boyko #:

Is this correct? I thought pointer can't be passed in this way.

I would do this:

[EDITED]

Yes it's correct. Your version (by reference) would be useful only if you need to change "pointer".
 
Manuel Alejandro Cercos Perez:

I noticed that from a derived class I can't access protected functions of an object from its base class (a pointer to other object), however from the base class I can access private functions of the other object (of the same type), and more strangely, from the derived class I can access and modify protected members from the base class directly, which seems contradictory to me.

Is it a bug? Or is it something to be expected and has some reasoning to it (which I'm curious to know I must say)?

This should not compile, as "otherPointer.ProtectedFunction()". So that's a bug.

   otherPointer.protectedMember = 2;

Other things are ok.

 
Alain Verleyen #:

This should not compile, as "otherPointer.ProtectedFunction()". So that's a bug.

Other things are ok.

Thanks, yes it would be expected that either both things or none of them work (none in this case)

 
Vladislav Boyko #:

The variant below compiles. I'm completely confused😄...

Does that mean I'm doing this for nothing:

Yes, and you are off-topic.
 
Alain Verleyen #:

This should not compile, as "otherPointer.ProtectedFunction()". So that's a bug.

Other things are ok.

I am not sure. I could imagine this is MQs solution to the missing "friend" keyword.

Because this works only inside the same scope of classes and inheritance structure.

EDIT:
Base class function Test1 shouldn't compile, right?
 
Dominik Egert #:
I am not sure. I could imagine this is MQs solution to the missing "friend" keyword.

Because this works only inside the same scope of classes and inheritance structure.

Why would the protected variable compiles while the protected method doesn't ? Both should not compile.
EDIT:
Base class function Test1 shouldn't compile, right?

If it's supposed to work like C++ then it should compile. Strange but fine.

 
Alain Verleyen #:
Why would the protected variable compiles while the protected method doesn't ? Both should not compile.

If it's supposed to work like C++ then it should compile. Strange but fine.

I thought a little about it, and maybe this is leaking permissions from copy constructor....

Since we have some keywords in c/c++ for opening a class, which are missing in mql, I cant deduce how it should be.


 

C++ reference :

A protected member of a class is only accessible

1) to the members and friends of that class;
2) to the members of any derived class of that class, but only when the class of the object through which the protected member is accessed is that derived class or a derived class of that derived class:

A private member of a class is only accessible to the members and friends of that class, regardless of whether the members are on the same or different instances

So I created some test code to check what it gives in MQL, compared to C++ :

//+------------------------------------------------------------------+
//| Compiler checking access                                         |
//+------------------------------------------------------------------+
class CDerived;

//---
class CBase
  {
private:
   int               privateMember;
   void              privateMethod();

protected:
   int               protectedMember;
   void              protectedMethod();

public:
   void              AccessPrivate(CBase *ptr);
   void              AccessPrivate(CDerived *ptr);
   void              AccessProtected(CBase *ptr);
   void              AccessProtected(CDerived *ptr);
  };

//---
class CDerived : public CBase
  {
public:
   void              AccessPrivateD(CBase *ptr);
   void              AccessPrivateD(CDerived *ptr);
   void              AccessProtectedD(CBase *ptr);
   void              AccessProtectedD(CDerived *ptr);
  };

//---
void CBase::privateMethod()      {};
//---
void CBase::protectedMethod()    {};
//---
void CBase::AccessPrivate(CBase *ptr)
  {
   int dummy = ptr.privateMember;
   ptr.privateMethod();
  }
//---
void CBase::AccessPrivate(CDerived *ptr)
  {
   int dummy = ptr.privateMember;
   ptr.privateMethod();
  }
//---
void CBase::AccessProtected(CBase *ptr)
  {
   int dummy = ptr.protectedMember;
   ptr.protectedMethod();
  }
//---
void CBase::AccessProtected(CDerived *ptr)
  {
//int dummy = ptr.protectedMember;    // NOT OK in MQL, it should compile : cannot access to protected member 'protectedMember' declared in class 'CBase'. Compile in C++.
   ptr.protectedMethod();
  }
//---
void CDerived::AccessPrivateD(CBase *ptr)
  {
//int dummy = ptr.privateMember;   // OK, C++ error: ‘int CBase::privateMember’ is private within this context
//ptr.privateMethod();             // OK, C++ error: ‘void CBase::privateMethod()’ is private within this context
  }
//---
void CDerived::AccessPrivateD(CDerived *ptr)
  {
//int dummy = ptr.privateMember;   // OK, C++ error: ‘int CBase::privateMember’ is private within this context
//ptr.privateMethod();             // OK, C++ error: ‘void CBase::privateMethod()’ is private within this context
  }
//---
void CDerived::AccessProtectedD(CBase *ptr)
  {
   int dummy = ptr.protectedMember;// NOT OK Compile in MQL but it should NOT, C++ error: ‘int CBase::protectedMember’ is protected within this context
//ptr.protectedMethod();           // OK, C++ error: ‘void CBase::protectedMethod()’ is protected within this context
  }
//---
void CDerived::AccessProtectedD(CDerived *ptr)
  {
   int dummy = ptr.protectedMember;
   ptr.protectedMethod();
  }

So there are 2 inconsistencies, that's MQL bugs. I asked explanation to MQ.

 
Alain Verleyen #:

C++ reference :

So I created some test code to check what it gives in MQL, compared to C++ :

So there are 2 inconsistencies, that's MQL bugs. I asked explanation to MQ.

I am confused with the first marked Line...

void CBase::AccessProtected(CDerived *ptr)
  {
//int dummy = ptr.protectedMember;    // NOT OK in MQL, it should compile. Compile in C++ cannot access to protected member 'protectedMember' declared in class 'CBase' 
   ptr.protectedMethod();
  }
The comment says "C++ cannot access"... So it should not compile in MQL either, right?

Did you maybe mean the following line?

   ptr.protectedMethod();

I haven't tested. And shouldn't this be "should not compile"?

EDIT: Assuming the C++ error message is correct.

EDIT2: I think I understood now. The comment has mislead me.

//int dummy = ptr.protectedMember;    // NOT OK in MQL, it should compile. Compiles in C++; MQL: cannot access to protected member 'protectedMember' declared in class 'CBase' 
 
Dominik Egert #:
I am confused with the first marked Line...

The comment says "C++ cannot access"... So it should not compile in MQL either, right?

Did you maybe mean the following line?


I haven't tested. And shouldn't this be "should not compile"?

EDIT: Assuming the C++ error message is correct.

EDIT2: I think I understood now. The comment has mislead me.

This is a MQL error message, sorry for the confusion. I edited my post.
Reason: