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.
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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With