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 classN
if [...]
m
as a member ofN
is protected, and R occurs in a member or friend of classN
, or in a member of a classP
derived fromN
, wherem
as a member ofP
ispublic
,private
, orprotected
There's a lot of letters in there. But there are basically two conditions:
R
is in a member or friend of the class. This handles thed.prot
example - we are in a member ofDerived
while accessing a protected member ofDerived
.R
is in a member of a derived class and the member being accessed is a member of the derived class instance. This handles theb.prot
example - we are in a member of a derived class, butprot
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
Vs: Unexpected Optimization Behavior with _Bitscanreverse64 Intrinsic
Combining Two Lists by Key Using Thrust
Convert Hexadecimal String with Leading "0X" to Signed Short in C++
Error Redeclaring a for Loop Variable Within the Loop
Enum Class Constructor C++ , How to Pass Specific Value
Capture _Line_ and _File_ Without #Define
What's the Deal with Boost.Asio and File I/O
Breaking Out from Socket Select
How to Initialize 'Std::Function' with a Member-Function
Why Isn't Memcpy Guaranteed to Be Safe for Non-Pod Types
Static Const Member Value VS. Member Enum:Which Method Is Better & Why
Why Is There No Base Class in C++
Are Lambdas Inlined Like Functions in C++
Defining Operator< for a Struct
Specifying a Concept for a Type That Has a Member Function Template Using Concepts Lite