6

The following code gives an compilation error for void b() { m = &A::a; }; stating that A::a() is protected. (Which it is - but that should be no problem)
However the compiler doesn't care when I write B::a(). Even though both mean the same I would prefer A::a() because it states explicitely that a() is defined in A.

So what is the reason why A::a() is forbidden?
EDIT
Maybe someone can find an example that would be problematic if A::a() was allowed in B::b(). If there is such an example, I will mark it as answer to the question.
/EDIT

#include <iostream>
#include <iomanip>
#include <string>
#include <cstdio>

class A {
protected:
  void a(){ std::cout << "A::a()" << std::endl; };
};

typedef void (A::*f)();
class B : public A {
public:
  void b() { m = &A::a; }; // wont compile
  // void b() { m = &B::a; }; // works fine
  void c() { (this->*m)(); };
protected:
  f m;
};

int main(){
  B b;
  b.b();
  b.c();
}

// compile with
// g++ -Wall main.cpp -o main

Explanation of the code:
In B I want to store a function pointer to a method in A to be able to call that later in B::c(). And yes, this happens in real life too. :-)

Pascal
  • 2,197
  • 3
  • 24
  • 34

3 Answers3

2

Because otherwise the outside world can find this protected member: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=11174.

See also http://gcc.gnu.org/ml/gcc-patches/2004-06/msg00610.html.

kennytm
  • 510,854
  • 105
  • 1,084
  • 1,005
  • Hmm, in my ignorance I still can't see why it is necessary. The function-pointer and thus the method is still protected in B. So it is not accessible from outside and if it was so would `B::b()` or am I missing the point completely? – Pascal Feb 22 '10 at 13:03
  • @tuner07, access protection is determined by the static type of the expression. The actual context in which you take the function-pointer doesn't come into play. – Georg Fritzsche Feb 22 '10 at 13:54
  • @gf If the access protection is determined by the static type of the expression it shouldn't be possible to call `A::a()` anywhere in B. But that is possible. So the rule applies only to the case where a function is stored into a function-pointer. I can still see no reason why `A::a()` must be prevented by the compiler. – Pascal Feb 22 '10 at 15:08
1

The reason should be similar to why you can't do this in B either:

class B: public A
{
    //...
    void foo(A& x) {
        x.a(); //error
    }

    void foo(B& x) {
        x.a(); //OK
    }
};

That protected doesn't mean that B can access the A part of any class as long it is an A / derived from A. The protected stuff is only available for this and other instances of B.

visitor
  • 8,564
  • 2
  • 26
  • 15
0

You try to access protected member through global namespace (A::a is ::A::a here), use B::A::a instead.

Tele
  • 1