Compro Prasad Compro Prasad - 3 months ago 19
C++ Question

How to access the address of base class member in inherited class member functions?

I have recently jumped into this whole world of classes, inheritance and templates in C++. But I got stuck. Please suggest me a way to solve this problem.

#include <iostream>

using namespace std;

template <typename type>
class a
{
protected:
type *b;
};

template <typename type>
class p : public a<type>
{
public:
void f()
{
type **q = &a<type>::b;
cout << *q << endl; // some other code in reality related to (*q)
}
};

int main()
{
p<int> obj;
obj.f();
return 0;
}


But it turned out to be unsuccessful:

x.cpp: In instantiation of ‘void p<type>::f() [with type = int]’:
x.cpp:26:9: required from here
x.cpp:9:9: error: ‘int* a<int>::b’ is protected
type *b;
^
x.cpp:18:16: error: within this context
type **q = &a<type>::b;
^
x.cpp:18:26: error: cannot convert ‘int* a<int>::*’ to ‘int**’ in initialization
type **q = &a<type>::b;
^


So I converted
type **q = &a<type>::b;
to
type* a<type>::* q = &a<type>::b;
. Then I got an additional error:

x.cpp: In instantiation of ‘void p<type>::f() [with type = int]’:
x.cpp:26:9: required from here
x.cpp:9:9: error: ‘int* a<int>::b’ is protected
type *b;
^
x.cpp:18:26: error: within this context
type* a<type>::* q = &a<type>::b;
^
x.cpp:19:13: error: invalid use of unary ‘*’ on pointer to member
cout << *q;
^


So I converted
b
to a
public:
member of
class a
from
protected:
. But that too gives me an error:

x.cpp: In instantiation of ‘void p<type>::f() [with type = int]’:
x.cpp:26:9: required from here
x.cpp:19:13: error: invalid use of unary ‘*’ on pointer to member
cout << *q;
^


Now I cant perform further modifications. I would love to know if the original code does not tamper with the class's characteristics of being protected.

Answer

You can still live with protected: type *b;, if you change below line in your code:

type **q = &a<type>::b;  // `protected: b` is not accessible in this context

to

type **q = &(this->b);  // we make sure that `protected: b` is accessed here

In such case, you are actually treating b as the inherited protected member.


Why to use this for accessing base class?
Refer: In a templated derived class, why do I need to qualify base class member names with "this->" inside a member function?


Another way

Originally linked by @Quentin, below post suggests the difference between a simple pointer and pointer to member:
Pointer-to-member confusion

So, in your original question actually you were trying to get a pointer to member variable by following syntax:

&a<type>::b  ==> int* a<int>::*

while you probably wanted &(a<type>::b), which would result in simple int*.
So it's one of the notebook examples, showing the benefits of putting parenthesis at right place! :-)