Reputation: 643
I am trying to get the address of a base class protected member variable.
Please help me understand what's wrong with this code:
class A
{
protected:
int m_;
};
class B : public A
{
public:
void Foo()
{
auto p1 = m_; // works but not what I want (B's member)
auto p2 = &m_; // works but not the the address which I'm looking for (B's member)
auto p3 = A::m_; // works but still not the address of the variable (A's member but not the address)
auto p4 = &A::m_; // doesn't work -> int A::m_’ is protected within this context
auto p5 = static_cast<A*>(this)->m_; // doesn't work -> int A::m_’ is protected within this context
auto p6 = &static_cast<A*>(this)->m_; // doesn't work -> int A::m_’ is protected within this context
}
private:
int m_;
};
Thanks
Gil
Upvotes: 0
Views: 106
Reputation: 30494
&static_cast<A*>(this)->m_
doesn't work because access to protected base class members is only allowed via a (reference or pointer to an) object of the same type as the class that the accessing function is a member (or friend) of.
That is, the following is not valid, even though A
is a base of B
class B : public A
{
public:
void Foo(const A& a)
{
auto i = a.m_; // Not valid
}
};
See [class.protected].
static_cast<A*>(this)
creates a pointer to A
, which B
cannot use to access A
's protected members.
The issue with &A::m_
is that it's not taking a pointer to the A::m_
member of the current object; it's actually forming a pointer-to-member. i.e.
struct A
{
int m_;
}
int main()
{
auto foo = &A::m_;
A a;
a.*foo; // Accesses the m_ member of a
}
You can use the somewhat unusual syntax &this->A::m_
to avoid hitting either of these pitfalls.
Upvotes: 3
Reputation: 16853
A problem you ran into is that auto p4 = &A::m_;
declares a pointer to data member. That is, the auto
resolved itself to int A::*
, not the int *
you had intended. You can get the intended pointer by adding parentheses:
auto p4 = &(A::m_);
or if you want to make sure you get the type you intend:
int * p4 = &(A::m_);
Upvotes: 3