简体   繁体   中英

Accessing base class member variable address from derived class when both have the same variable name

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

&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. ie

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.

Example

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_);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM