7
class A {
public:
   A() {auto tmp = &A::foo;}
protected:
   void foo() {}
};

class B : public A {
public:
   B() {auto tmp = &A::foo;}
};

Class A compiles no problem. Class B yields a compilation error:

'A::foo' : cannot access protected member declared in class 'A'

Why is that, what's the rationale? Is there a way to circumvent this (if I need that pointer for a callback, std::function etc.)?

Violet Giraffe
  • 32,368
  • 48
  • 194
  • 335

4 Answers4

4

Why is that, what's the rationale?

In general, a derived class can only access protected members of the same derived class, not of the base class itself or arbitrary classes with the same base class. So B can access protected members of A via B, but not directly via A.

Is there a way to circumvent this?

The inherited member is also a member of B, and can be accessed as such:

auto tmp = &B::foo;
Mike Seymour
  • 249,747
  • 28
  • 448
  • 644
2

If you were able to take a pointer to A::foo, you could use it to invoke foo on an object of type A or of type C derived from A:

class B : public A {
public:
    void xx(A a) { auto tmp = &A::foo; a.*tmp(); }  // illegal
}

Instead, take a pointer to B::foo; this is fine because you can only use it on objects of type B, your own class.

ecatmur
  • 152,476
  • 27
  • 293
  • 366
1

Presumably for safety. If you could get a pointer to that member and give it to absolutely anyone without having some kind of alarm bell going off, that would be risky.

Here's a workaround (others may know better):

class A {
public:
    A() {auto tmp = &A::foo;}
protected:
    void foo() {}
};

class B : public A {
public:
    B() {auto tmp = &B::foo;}
};

EDIT - thought you might need a using A::foo but you don't even need that. Works without. See:

Access to method pointer to protected method?

Community
  • 1
  • 1
1

You can access it through B, that is :

class B : public A {
public:
   B() {auto tmp = &B::foo;}
};

You cannot access &A::Foo from outside B, since it is protected, but you can through inheritance (since Foo becomes a member of B through inheritance), that is, by calling &B::Foo

quantdev
  • 23,517
  • 5
  • 55
  • 88