Access to Protected Member Through Member-Pointer: Is It a Hack

Access to protected member through member-pointer: is it a hack?

The fact that a member is not accessible using class member access expr.ref (aclass.amember) due to access control [class.access] does not make this member inaccessible using other expressions.

The expression &Derived::value (whose type is int Base::*) is perfectly standard compliant, and it designates the member value of Base. Then the expression a_base.*p where p is a pointer to a member of Base and a_base an instance of Base is also standard compliant.

So any standard compliant compiler shall make the expression other.*(&Derived::value); defined behavior: access the member value of other.

protected members are not accessible through a pointer or object

You are trying to access the member of an other instance of your mother class:
classProb, but inheritance make you able to access protected member of your own parent class only.

One way to correcting (but it strongly depend of what you are trying to do) is to put an getter of _probClass in your Training class and call it in your test, for instance for the _probCalc member:

public:
(Type) Training::getProbCalc() {
return _probCalc;
}

the to change your call in the loop:

for (it3 = classProb.getProbCalc().begin(); it3 != classProb.getProbCalc().end(); it3++)

If you are trying to acces your own member inherited by your mother instance just call them directly. For instance:

for (it3 = _probCalc().begin(); it3 != _probCalc().end(); it3++)

Derived class cannot use member pointer to protected base class member

By trial and error I found a solution that makes some sense. Even if it is a base class inherited member that you are pointing to, the pointer should still be a member pointer of the Derived class. So, the following code works:

include <stdio.h>

class Base
{
protected:
int foo;
int get_foo() { return foo; }
};

class Derived : public Base
{
public:
void bar()
{
int Derived::* i = &Derived::foo;
this->*i = 7;
printf("foo is %d\n", get_foo());
}
};

int main()
{
Derived d;
d.bar();
}

If Base's members are scoped as private then you get the expected lack of access error.

Cannot access protected member of another instance from derived type's scope

The rule in [class.access.base] is:

A member m is accessible at the point R when named in class N if [...]

  • m as a member of N is protected, and R occurs in a member or friend of class N, or in a member of a class P derived from N, where m as a member of P is public, private, or protected

There's a lot of letters in there. But there are basically two conditions:

  1. R is in a member or friend of the class. This handles the d.prot example - we are in a member of Derived while accessing a protected member of Derived.
  2. R is in a member of a derived class and the member being accessed is a member of the derived class instance. This handles the b.prot example - we are in a member of a derived class, but prot is not a member of the derived class.

In other words, Derived can access Base's protected members - but only in the case that it is accessing its own subobject's protected members. It cannot access other Base object's protected members. This makes sense when you consider that this other Base could easily be SomeOtherDerived, in which case that's just another unrelated object to us that we have no special access privileges to.

Why can't I access a protected member from an instance of a base class?

You can access the protected members of a base class only through a pointer or reference to an object of the derived type.

If you change

void copy_a_from_bar(bar& o){
a = o.a;
}

to

void copy_a_from_bar(bar& o){
foo& foo_ref = o;
a = o.a; // OK. Accessing it through `bar&`
a = foo_ref.a; // Not OK. Accessing it through `foo&`
}

you will see the same error.

This SO answer gives an indication of why allowing access to the protected members of the base class will be a potential breach of the protected status of the base class members.

Say you have:

class baz : public foo
{
void update_a(foo& f)
{
f.a = 20;
}
};

and use:

bar x;
baz z;
z.update_a(x);

If this were allowed, baz will be able to change the values of members of bar. That is not good.

Accessing protected members in a derived class

A class can only access protected members of instances of this class or a derived class. It cannot access protected members of instances of a parent class or cousin class.

In your case, the Derived class can only access the b protected member of Derived instances, not that of Base instances.

Changing the constructor to take a Derived instance will solve the problem.

Cannot access protected member

A common misunderstanding.

Inside Derived::foo(), you can access protected base members of objects of class Derived. However, *b is not of type Derived. Rather, it is of type Base, and so it does not have anything to do with your class.

It's a different matter if you take a Derived* as an argument -- then you will indeed have access to protected base members.


Let's spell it out:

struct Derived;

struct Base
{
int f(Derived *);
protected:
int x;
private:
int y;
};

struct Derived : public Base
{
int g(Base *);
int h(Derived *);
};

int Derived::g(Base * b)
{
return b->x; // error, protected member of unrelated class
return b->y; // error, private member of different class
}

int Derived::h(Derived * d)
{
return d->x; // OK, protected base member accessible in derived class
return d->y; // error, private member of different class
}

int Base::f(Derived * d)
{
return d->x; // OK, d converts to Base*
return d->y; // OK, ditto
}


Related Topics



Leave a reply



Submit