2

The following code does not compile in GCC 4.9.1:

class A
{
protected:
   virtual void f() {}

};

class B : public A
{
protected:
   virtual void f() override { A* a = new A; a->f(); }
};

I get the following:

header.h: In member function 'virtual void B::f()':
header.h:51:17: error: 'virtual void A::f()' is protected

I would have expected this to compile.

Why does it fail? Is there a better way than making f() public?

Silicomancer
  • 8,604
  • 10
  • 63
  • 130

2 Answers2

1
A* a = new A; a->f();

IS the problem here: You cannot call f() from a since it is not public, and not accessible to B in the member function scope.


It Works!
Arnav Borborah
  • 11,357
  • 8
  • 43
  • 88
  • Ok. The strange thing is I could swear I have seen something like this before and it successfully compiled. – Silicomancer Sep 07 '16 at 21:32
  • You may have marked `f()` public before... I have added an example anyways – Arnav Borborah Sep 07 '16 at 21:34
  • Maybe. Could it depend from the compiler? I used to use VC++ – Silicomancer Sep 07 '16 at 21:40
  • 1
    Compiling your example on Visual Studio 2015, I get similar errors, compiling on g++ gives similar errors as well. – Arnav Borborah Sep 07 '16 at 21:40
  • Yeah, I'm not sure about this either. I mean, a copy constructor can access protected and private member variables from the object passed as an argument, right? How else would copy constructors work? So why can't an object of class A call a protected member function of another object of the same class? – Dan Korn Sep 07 '16 at 22:04
  • I guess it's different for inherited classes than for the base class. Every C++ class is implicitly a friend of itself, but inherited classes are not. – Dan Korn Sep 07 '16 at 22:05
  • I understand the rule. However I don't understand why it exists. Where is the harm in calling protected members of some other object of base type? When using virtual functions this could be useful. – Silicomancer Sep 08 '16 at 07:12
1

You cannot cross-invoke protected methods between different instances of a class or instances of a parent class just because B inherit from that class.

Anyway B is already an A.
Did you intend to call A::f();?

class B : public A {
protected:
    virtual void f() override { A::f(); /* ... whatever ... */ }
};
skypjack
  • 49,335
  • 19
  • 95
  • 187