Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why calling a protected static method in derived classes is allowed?

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.

like image 388
Boris Dalstein Avatar asked Jun 04 '13 08:06

Boris Dalstein


2 Answers

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.

like image 79
Andy Prowl Avatar answered Oct 10 '22 11:10

Andy Prowl


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.

like image 41
Tony Delroy Avatar answered Oct 10 '22 12:10

Tony Delroy