13

Invoking a protected constructor in a derived class is not allowed, as explained here.

The accepted answer explains that protected grants access to members of an object of base class A only when that object of class A is a subobject of class B. So far, so good.

But then, why is it allowed (at least in GCC 4.6.3) to call static protected methods? Specifically, it doesn't make any sense to me that the following compiles, while the commented line does not:

class A 
{
protected:
    A() {}
    static A makeA() { return A(); }
};

class B: public A
{
public:
    static A makeAFromB()
    {
        return makeA(); // compiles
        // return A();  // does not compile
    }
};

Philosophically, a constructor is pretty much like a static method returning an object of class A, reason why I don't get the difference in behaviour here.

Community
  • 1
  • 1
Boris Dalstein
  • 7,015
  • 4
  • 30
  • 59

3 Answers3

12

But then, why is it allowed (at least in GCC 4.6.3) to call static protected methods?

Because that's what the Standard says. The constraints that apply to the accessibility of protected members (and that the answer you linked explains very well) are defined in paragraph 11.4/1 of the C++11 Standard, whose first sentence specifies:

An additional access check beyond those described earlier in Clause 11 is applied when a non-static data member or non-static member function is a protected member of its naming class (11.2). [...]

The additional access check does not apply to static members or static member functions.

Andy Prowl
  • 124,023
  • 23
  • 387
  • 451
2

You're right that the way protected only grants access to the embedded base object can be surprising... but there's a good reason for it. Say you have a couple classes derived from Base, and a method in one of those classes wanted to do things to an arbitrary Base object via some reference or pointer... it might be that the Base it's fiddling with is part of the other derivation chain, which has other behavioural expectations of the Base object given the usage it makes of the protected member functions. You're effectively removing the encapsulation that the other derived class intended, preventing it enforcing intended invariants, stepping outside the world of good OO behaviours.... Applying this insight to your specific scenario, the C++ rules are preventing you using that protected constructor to make a subobject that was expected to have invariants policed by some derived class, when there is actually no derived object into which that Base object will be embedded.

Separately, the way protected works for constructors has clear utility - it prevents construction of the class (using that constructor) except as a subobject of the derived class, or from member functions of the base class (such as makeA in your example) - whether they're static or non-static member functions is irrelevant... all member functions always have full to the class.

What would be the utility in ignoring the intuitive meanings of private/protected/public for static member functions? You're saying you expect them to be effectively private, if that's behaviour you want then just make them private / if you need them accessible leave them protected. Clearly the protected access is limited as per the justification in my first paragraph.

Tony Delroy
  • 102,968
  • 15
  • 177
  • 252
  • Thanks for the answer :) In fact, what I expected was that a protected constructor of `Base` could be invoked from `Derived`. When I realized it wasn't possible, I tried using the protected `makeA` that I expected to work, but wasn't sure anymore since my previous expectation turned false (and this simple hacking provides exactly the same functionality). But you're right concerning the title of my question: obviously protected static methods should be callable in derived classes, otherwise there would be no difference with private static methods. – Boris Dalstein Jun 04 '13 at 10:14
  • @Boris: "expected was that a protected constructor of Base could be invoked from Derived" - yes, been there expected that too! :-) - hope the reasoning above helps explain the "why not" aspect. The critical difference with `makeA` is that the implementation's still under `A`'s control... it's allowed to decide the boundaries of `A`'s encapsulation, where-as letting the derived class use the constructor forgoes control. Cheers. – Tony Delroy Jun 04 '13 at 10:22
  • the reasoning above indeed helped, as well as your additional comment :) I'm still quite annoyed that I can't invoke the destructor, but well, at least there's a good reason for this ;-) – Boris Dalstein Jun 04 '13 at 10:31
0

Static methods are inherited in the sense that they're available amongst the child class's methods. We can call a static method using the child class's name, or using an instance of the child class, or without qualification in the body of a child class.