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.
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.
Related
I found some statements regarding my above question, but there are diferent claims:
The static member function can't access non-static data members/functions of a class. The vPTR is non-static data member, hence a static member function can't access vPTR.
No, because it doesn't make any sense in C++.
Virtual functions are invoked when you have a pointer/reference to an instance of a class. Static functions aren't tied to a particular instance, they're tied to a class. C++ doesn't have pointers-to-class, so there is no scenario in which you could invoke a static function virtually.
Which is one is right and for what reason?
No, static functions cannot be virtual in C++.
It would occasionally be useful if the function does not depend on any members of the class but is, in a sense, dependent on the type:
struct Animal
{
static virtual std::string whatNoiseDoIMake() = 0;
};
struct Dog : Animal
{
static std::string whatNoiseDoIMake()
{
return "woof"s;
}
};
The reason it's not part of the language are due to it not being proposed to and accepted by the C++ standards committee. My example can be solved using type traits, which weakens the case for such constructs to be allowed.
As for const, that really is about the possibility of modifying non-mutable class members. It's harder to concoct a meaningful example of a const static member function. Perhaps it could apply to static members, but then such members are reachable via :: anyway with (interestingly) access specifiers discarded.
Which is right one and for what is the exact reason?
The static member function can't access non-static data members/functions of a class. The vPTR is non-static data member, hence a static member function can't access vPTR.
No, because it doesn't make any sense in C++.
Virtual functions are invoked when you have a pointer/reference to an instance of a class. Static functions aren't tied to a particular instance, they're tied to a class. C++ doesn't have pointers-to-class, so there is no scenario in which you could invoke a static function virtually.
The first statement is correct, in the sense that static member functions do not have access to the *this pointer, they have a class scope. A static member is shared by all instances of the class.
In the second statement the first part is opinion-based, one can argue that it could be useful, as #Bathsheba points out. The second part is correct.
Regardless of the possible sense or merit of the use of such construct, the standard is clear as to why virtual static member functions are not allowed:
11.7.2 Virtual functions [class.virtual#11]
[ Note: The virtual specifier implies membership, so a virtual function cannot be a non-member ([dcl.fct.spec]) function.
Nor can a virtual function be a static member, since a virtual function call relies on a specific object for determining which function to invoke.
A virtual function declared in one class can be declared a friend ([class.friend]) in another class.
— end note
]
No, they can't.
Virtual members were designed to deal with instances of the class.
Static members do not deal with instances, they relate only to class.
How would you select which "virtual static" function to call depending on instance (as in dynamic polymorphism) as there is no connection to any instance?
These are just two different mechanism that have mutually excluding dependencies.
Can static functions be virtual in C++?
No.
The static member function can't access non-static data members/functions of a class.
That isn't quite right: static methods can absolutely access non-static (instance) members ... if you give them an instance. They have access, they just don't have a default this object to operate on.
The vPTR is non-static data member, hence a static member function can't access vPTR
We don't need to dwell on implementation details such as vtables. It's sufficient to say that virtual dispatch depends on the dynamic type of an object, and if you don't have an object, there's no type ambiguity that could possibly benefit from virtual dispatch.
C++ doesn't have pointers-to-class, so there is no scenario in which you could invoke a static function virtually
Note that in languages with this facility, you still don't need a special system for static virtuals - it's generally just that classes are objects. So in that case, static methods of a regular class are still instance methods of the class object.
The first statement assumes a "vptr". That refers to a common implementation technique in C++ compilers, where each object with virtual functions contains a hidden pointer to some "vtable", which in turn contains pointers to the virtual functions.
This is however an implementation detail of those compilers. They've chosen that implementation because it's a possible implementation, allowed by the C++ standard.
One of the reasons it's allowed is because the C++ standard says that you always need an object to call a virtual function on, so there's always an object to store that "vptr" in.
The first answer therefore confuses cause and effect. Implementations can use a "vptr" because virtual functions need an object and therefore can't be static, not the other way around.
Static Functions can not be virtual in c++ since the concept leads to compile error and is basically resolved at run time
I am currently working with Big C++ 2nd Edition, using Code::Blocks 17.12, on the chapter for inheritance
The book introduces the protected variable type for cases in which you want to allow a derived class to access said variable.
The book also forewarns that protected elements suffer from some of the pitfalls of a public variable: in the worst cases derived class members can corrupt the base class data
The book demos the use of a protected member in a clock program in a dedicated section in which they introduce this, but in the final code they ultimately went with setting the variable to private and then using some get_ helper functions to access this private data. This combo of private and using helper functions always returned errors in my IDE and I wasn't able to pull that off
Take this simple example I created for P8.1, a employee record for a programmer, with an employee base class and programmer derived class. I created the following ctor, with the variables name and sal set to protected status in the base class
Programmer::Programmer(string p_name, double p_sal)
:Employee(get_name(), get_sal())
{
name=p_name;
sal=p_sal;
}
With this code, the program works perfectly.
Based on the textbook, if the variables name and sal were set to private status in the base, then I should be able to execute the code also, granted that I am using a get_ helper function I created to accessed the data.
Can anyone explain what the issue is here? Should I be ok with using protected or is there truly a way to keep all of my variables private for classes?
I also found this on https://learn.microsoft.com/en-us/cpp/cpp/protected-cpp?view=vs-2019
Protected members that are also declared as static are accessible to any friend or member function of a derived class. Protected members that are not declared as static are accessible to friends and member functions in a derived class only through a pointer to, reference to, or object of the derived class.
I have not covered static so far, So I ultimately tried a bunch of different combinations with pointers and references, none of which worked either.
I am trying to understand when to use protected vs when to use private basically and the book isn't being clear on that. Any ideas?
For some reason I thought when calling the base class constructor you needed to provide helper functions to access the private data.
Since the base ctor is already public, and by feeding it the parameters for the derived class ctor it will construct the derived class obj properly, allowing get_ func's to read its private variables
Programmer::Programmer(string p_name, double p_sal)
:Employee(p_name, p_sal)
{}
I wasn't understanding this in the book, thank you all for helping clarify
I have a function public void myFunction(foo); and public void myFunction(foo, bar); in my parent class. I want these functions included in my derived class, but privately. You can declare it in the derived class' private section by using BaseClass::myFunction(). Note that it doesnt take any parameters in the function. But if there are two implementations of myFunction like I have in my case, it won't work since it can't distinguish between the two functions. How do I implement both functions privately?
Based on what you've said in your comment about your professor's instruction to use inheritance, more than whether it's a good design choice, I think you are expected to use private inheritance.
Private inheritance is a valid feature of C++, but its often not a good design choice. I wont go into that, I'm not recommending it in general, I'll leave you to look it up elsewhere on SO, but also recommend Scott Meyer's books effective C++ & more effective C++ which covers this.
(protected inheritance on the other hand is very unusual)
In your question you seem to be starting from public inheritance and trying to make some inherited functionality private via using. This is a bad design choice as mentioned in comments. It violates the Liskov substitution principle. Since PUBLIC inheritance implies is-a, we can imagine the code that creates a base class reference to an object of the derived type, what then is supposed to happen when we try to call the hidden functionality with that base class reference?
Derived d;
Base& b = d;
b.HiddenFunction(); // calling the function on d even though you thought you hid it
If instead you use private inheritance you can then use using to publicise those privately inherited functions which are safe to expose on the derived class.
class OrderedLinkedList : private LinkedList
{
public:
using LinkedList::ItemCount; // expose some specific base functionality
};
If using doesn't do the job due to overloaded functions, then you can add just those overloads that you want to provide and implement them just by calling the base function. In such cases, if you need to clarify whether to call the base or derived version you can prefix the function name with the class name e.g.
void SomeFunction()
{
// call base version, not this derived version recursively
NameOfBaseClass::SomeFunction();
}
Within the derived class implementation, the public and protected members of the (privately) inherited base class are accessible without the need to do anything like add a using.
Private inheritance is not an is-a relationship like public inheritance since we cannot refer to the derived objects as references/pointers to the base. Private inheritance is "implemented-in-terms-of".
Since private inheritance is not an is-a, one cannot substitute such derived objects for the base and as such the liskov substitution principle just doesn't apply.
Following code prints "I'm B!". It's a bit strange because B::foo() is private. About A* ptr we can say that its static type is A (foo is public) and its dynamic type is B (foo is private). So I can invoke foo via pointer to A. But this way I have access to private function in B. Can it be considered as encapsulation violation?
Since access qualifier is not part of class method signature it can lead to such strange cases. Why does in C++ access qualifier is not considered when virtual function is overridden? Can I prohibit such cases? What design principle is behind this decision?
Live example.
#include <iostream>
class A
{
public:
virtual void foo()
{
std::cout << "I'm A!\n";
};
};
class B: public A
{
private:
void foo() override
{
std::cout << "I'm B!\n";
};
};
int main()
{
A* ptr;
B b;
ptr = &b;
ptr->foo();
}
You have multiple questions, so I'll try to answer them one-by-one.
Why is in C++ access qualifier not considered when virtual function is overridden?
Because access qualifiers are taken into account by the compiler after all overload resolutions.
Such behavior is prescribed by the Standard.
For example, see on cppreference:
Member access does not affect visibility: names of private and privately-inherited members are visible and considered by overload resolution, implicit conversions to inaccessible base classes are still considered, etc. Member access check is the last step after any given language construct is interpreted. The intent of this rule is that replacing any private with public never alters the behavior of the program.
The next paragraph described the behavior demonstrated by your example:
Access rules for the names of virtual functions are checked at the call point using the type of the expression used to denote the object for which the member function is called. The access of the final overrider is ignored.
Also see the sequence of actions listed in this answer.
Can I prohibit such cases?
No.
And I don't think you will ever be able to do so, because there's nothing illegal in this behavior.
What design principle is behind this decision?
Just to clarify: by "decision" here I imply the prescription for the compiler to check the access qualifiers after overload resolution.
The short answer: to prevent surprises when you're changing your code.
For more details let's assume you're developing some CoolClass which looks like this
class CoolClass {
public:
void doCoolStuff(int coolId); // your class interface
private:
void doCoolStuff(double coolValue); // auxiliary method used by the public one
};
Assume that compiler can do overload resolution based on public/private specifiers. Then the following code would successfully compile:
CoolClass cc;
cc.doCoolStuff(3.14); // invokes CoolClass::doCoolStuff(int)
// yes, this would raise the warning, but it can be ignored or suppressed
Then at some point you discover that your private member function is actually useful for the class client and move it to "public" area. This automatically changes the behavior of the preexisting client code, since now it invokes CoolClass::doCoolStuff(double).
So the rules of applying access qualifiers are written in a manner that does not allow such cases, so instead you will get the "ambiguous call" compiler error in the very beginning. And virtual functions are no special case for the same reason (see this answer).
Can it be considered as encapsulation violation?
Not really.
By converting pointer to your class into a pointer to its base class you're actually saying: "Herewith I would like to use this object B as if it's an object A" - which is perfectly legal, because the inheritance implies "as-is" relation.
So the question is rather, can your example be considered as violating contract prescribed by the base class? It seems that yes, it can.
See the answer to this question for alternative explanation.
P.S.
Don't get me wrong, all this doesn't mean at all that you shouldn't use private virtual functions. On the contrary, it's often considered as a good practice, see this thread. But they should be private from the very base class. So again, the bottom line is, you should not use private virtual functions to break public contracts.
P.P.S. ...unless you deliberately want to force client to use your class via the pointer to interface / base class. But there are better ways for that, and I believe the discussion of those lies beyond the scope of this question.
Access qualifiers like public, private, etc. are a compile time feature, while dynamic polymorphism is a runtime feature.
What do you think should happen at runtime when a private override of a virtual function is called? An exception?
Can it be considered as encapsulation violation?
No, since the interface is already published through the inheritance, it isn't.
It's perfectly fine (and might be intended), to override a public virtual function from the base class with a private function in the derived class.
Suppose there are two classes A and B:
class A {};
class B {};
In what aspects differ the two examples below?
Example 1:
class C : public A, public B {};
Example 2:
class C
{
//private
friend class A;
friend class B;
}
A friend can touch the private parts (pun only slightly intentional! ;) ) of whatever it is friend of, but nothing of A and B are part of C - it just means that "A and B can touch C's private bits"). Anything "less" than private is of course also available to A and B, so if C has protected or public members, that will also be available.
When you inherit, the A and B becomes part of C. Any private sections of A and B are not available to C. In the "is-a" vs. "has-a" nomenclature, C now is-a A and is-a B - in other words, it's inherited from A, so it "behaves like A from an interface perspective.
There are several big differences. Inheritance and friendship are very different.
With friendship, class C is NOT an instance of class A or class B. Therefore, if you have a function like:
void processMyClass(A* a);
you cannot pass it an instance of C whereas, if C subclasses A (publicly), it IS an instance of A.
With friendship, class A and B can touch all the private member data and functions of C. With inheritance, class C can touch the public and protected members of A and B.
Friendship is not inherited. This means, for example:
class D : public C
{
private:
void foo() {
// A and B cannot call this function
}
}
In the context you're using, to answer your question to the best of my ability, friends simply allow your classes to share protected/private data, while inheritance will do the same, except there'll be a deeper relationship, where the classes are one in the same (such as with casting).
While the answers you've gotten are reasonably accurate, I don't think they're really complete. In particular, although they explain what the difference between friendship and inheritance is, they don't really explain much about which you should use when, or how the difference affects your code.
The primary use of inheritance (in C++) is to define an interface in a base class, and implement that interface in each of a number of derived classes. The parts of the interface that a derived class must implement will normally be signified by pure virtual functions in the base class.
The primary use of friendship in C++ is to define something that forms part of an interface, but for syntactical reasons can't be a member function. One extremely common example is a stream insertion or extraction operator. To implement these as member functions, they'd have to be members of the stream class. Since we don't want to modify the stream class constantly, they're instead free functions that take a reference to a stream as their left parameter, and a reference to a (possibly const) object of the type they insert/extract as their right operand.
These don't necessarily have to be friends of the class--they can be written to use only the class' public interface. If you do that, though, it generally means the class is exposing more in its public interface than is otherwise necessary. The interface is no longer minimal, which tends to indicate a problematic design.
One note though: you can define a friend function inside a class definition:
class Foo {
// ...
friend std::ostream &operator<<(std::ostream &os, Foo const &f) {
// ...
}
};
At first this may seem strange (and syntactically it is, somewhat). Even though it's defined inside the class definition, the friend means that this is not a member function. At least in my opinion, this reflects its situation fairly accurately: conceptually, it's part of the class. It has access to private members, just like any other member of the class. The fact that it's a free function rather than a member function is purely an implementation artifact that has essentially nothing to do with the code's design.
That also points to another difference between friendship and inheritance: with inheritance, you're normally dealing primarily with member functions. Each member function still receives a this pointer, so each member function is directly associated with a specific instance of the class. Yes, you can define it to also receive (a pointer or reference to) another instance of the class if desired, but it always receives this, regardless. A friend (function or class) doesn't get this--the friend declaration just means that the names that are private to that other class are visible to the friend. To get access to an actual instance of that class, you typically need to pass it as a parameter, or something on that order.
Finally, I'll note that the preceding sort of ignores the possibilities of private or protected inheritance. Private inheritance normally means that the derived class is implemented in terms of the base class. This can be handy if (for example) the derived class is similar to the base class, but isn't related in the design--i.e., you're not asserting that an instance of the derived class can be used anywhere an instance of the base class was needed. Its use of the base class is an implementation detail that the rest of the world doesn't need to know or care about.
Protected inheritance is pretty much a mistake. It's allowed because it's consistent with public, private and protected members (which do make sense) but for inheritance, protected simply doesn't seem to accomplish anything useful.