In The C++ Programming Language, 4th Edition, at §20.5.2 "Access to Base Class" (page 605), it says (regarding private inheritance):
private bases are most useful when defining a class by restricting
the interface to a base so that stronger guarantees can be
provided.For example, B is an implementation detail of Z .The Vector
of pointers template that adds type checking to its Vector base
from §25.3 is a good example.
It's not clear what Bjarne Stroustrup is trying to say here. How can be a class be defined by restricting "the interface" to a base? What does he mean by "stronger guarantees"?
Lets take a very simple example:
// A simple class with a *public* member
class A
{
public:
int a;
};
// Use private inheritance
class B : private A
{
public:
int b;
};
// Use public inheritance
class C : public A
{
public:
int c;
};
// ...
B my_b;
my_b.a = 0; // Invalid, the member a is private due to the private inhericance
C my_c;
my_c.a = 0; // Valid, because the inheritance is public
The private inheritance restricts access to the members of the base class. Even if the A::a member variable is public, due to the private inheritance it becomes private in the sub-class B.
Let's stay with the example of the vector. A vector is just a container of Ts. Now let's say you want to build a type that behaves just like a vector, but adds some additional runtime checks. I don't have my copy of TC++PL at hand right now, so let's just make up a constraint: For example, let's say your vector is only allowed to hold even numbers. Attempting to insert an odd number will result in a runtime error. Let's call this new class even_vector and the version without the runtime checks base_vector.
even_vector provides stronger runtime guarantees than base_vector: It is guaranteed that all of its elements are even.
Assuming that your base_vector is designed to work nice as a base class (which std::vector typically does not), you might now be tempted to use public inheritance to implement even_vector in terms of base_vector. After all, the functionality is the same, you simply have some additional runtime checks in the even_vector case on top of the functionality provided by base_vector. However, if you were to use public inheritance here, you would violate the Liskov Substitution Principle: You cannot use an even_vector wherever you use a base_vector. In particular, the even_vector will break in cases where you are inserting odd numbers into a base_vector. This is bad, as now all code that is written for base_vector must account for the fact that some of the base_vectors cannot deal with odd numbers.
With private inheritance you do not have this problem: Here the fact that even_vector inherits from base_vector is a detail of the implementation. Clients cannot use even_vector where a base_vector is expected, so the problem from above does not occur, but we still get the benefits of code reuse.
That being said, using private inheritance for code reuse is a practice that is discouraged by many. An arguably better way would be to use composition here instead, that is, add a private base_vector member to even_vector instead. The advantage of that approach is that it severely reduces coupling between the two classes, as even_vector is no longer able to access any non-public parts of base_vector.
how can be a class be defined by restricting "the interface" to a base?
By making the inheritance private. When the inheritance is private, the interface of the base class is restricted to the member functions and not available outside. The access specifier can be given in the list of bases:
class A : private B
// ^^^^^^^
What does he mean by "stronger guarantees"?
Any guarantee that is not given by the base, or is a superset of a guarantee given by the base.
For example, the guarantee that "behaviour is always well defined" is stronger than "Behaviour is well defined only if input is not null". Another example: "The function does not throw" is stronger than "The function will not throw unless the copy constructor throws".
Allow us to look at a possible situation with interfaces to help build up the picture.
class poison {
public:
virtual void used() = 0;
};
class food {
public:
virtual void eat();
protected:
void poisonConsumed(poison& p);
}
class cheese : public food, private poison {
public:
virtual void eat() override {
poisonConsumed(*this);
}
private:
void used() override;
}
This presents cheese to the outside world as 'not a poison' - ie nothing outside the class can know that it's a poison, and it could be made 'not a poison' to no impact on anything using it.
The cheese however, can pass itself to anything expecting a poison which is then free to call used(); even though it's private in cheese.
Related
By an interface (C# terminology) I mean an abstract class with no data members. Thus, such a class only specifies a contract (a set of methods) that sub-classes must implement. My question is: How to implement such a class correctly in modern C++?
The C++ core guidelines [1] encourage the use of abstract class with no data members as interfaces [I.25 and C.121]. Interfaces should normally be composed entirely of public pure virtual functions and a default/empty virtual destructor [from C.121]. Hence I guess it should be declared with the struct keyword, since it only contains public members anyway.
To enable use and deletion of sub-class objects via pointers to the abstract class, the abstract class needs a public default virtual destructor [C.127]. "A polymorphic class should suppress copying" [C.67] by deleting the copy operations (copy assignment operator, copy constructor) to prevent slicing. I assume that this also extends to the move constructor and the move assignment operator, since those can also be used for slicing. For actual cloning, the abstract class may define a virtual clone method. (It's not completely clear how this should be done. Via smart pointers or owner<T*> from the Guidelines Support Library. The method using owner<T> makes no sense to me, since the examples should not compile: the derived function still does not override anything!?).
In C.129, the example uses interfaces with virtual inheritance only. If I understand correctly, it makes no difference if interfaces are derived (perhaps better: "implemented"?) using class Impl : public Interface {...}; or class Impl : public virtual Interface {...};, since they have no data that could be duplicated. The diamond problem (and related problems) don't exist for interfaces (which, I think, is the reason why languages such as C# don't allow/need multiple inheritance for classes). Is the virtual inheritance here done just for clarity? Is it good practice?
In summary, it seems that:
An interface should consist only of public methods. It should declare a public defaulted virtual destructor. It should explicitly delete copy assignment, copy construction, move assignment and move construction. It may define a polymorphic clone method. I should be derived using public virtual.
One more thing that confuses me:
An apparent contradiction: "An abstract class typically doesn't need a constructor" [C.126]. However, if one implements the rule of five by deleting all copy operations (following [C.67]), the class no longer has a default constructor. Hence sub-classes can never be instantiated (since sub-class constructors call base-class constructors) and thus the abstract base-class always needs to declare a default constructor?! Am I misunderstanding something?
Below is an example. Do you agree with this way to define and use an abstract class without members (interface)?
// C++17
/// An interface describing a source of random bits.
// The type `BitVector` could be something like std::vector<bool>.
#include <memory>
struct RandomSource { // `struct` is used for interfaces throughout core guidelines (e.g. C.122)
virtual BitVector get_random_bits(std::size_t num_bits) = 0; // interface is just one method
// rule of 5 (or 6?):
RandomSource() = default; // needed to instantiate sub-classes !?
virtual ~RandomSource() = default; // Needed to delete polymorphic objects (C.127)
// Copy operations deleted to avoid slicing. (C.67)
RandomSource(const RandomSource &) = delete;
RandomSource &operator=(const RandomSource &) = delete;
RandomSource(RandomSource &&) = delete;
RandomSource &operator=(RandomSource &&) = delete;
// To implement copying, would need to implement a virtual clone method:
// Either return a smart pointer to base class in all cases:
virtual std::unique_ptr<RandomSource> clone() = 0;
// or use `owner`, an alias for raw pointer from the Guidelines Support Library (GSL):
// virtual owner<RandomSource*> clone() = 0;
// Since GSL is not in the standard library, I wouldn't use it right now.
};
// Example use (class implementing the interface)
class PRNG : public virtual RandomSource { // virtual inheritance just for clarity?
// ...
BitVector get_random_bits(std::size_t num_bits) override;
// may the subclass ever define copy operations? I guess no.
// implemented clone method:
// owner<PRNG*> clone() override; // for the alternative owner method...
// Problem: multiple identical methods if several interfaces are inherited,
// each of which requires a `clone` method?
//Maybe the std. library should provide an interface
// (e.g. `Clonable`) to unify this requirement?
std::unique_ptr<RandomSource> clone() override;
//
// ... private data members, more methods, etc...
};
[1]: https://github.com/isocpp/CppCoreGuidelines, commit 2c95a33fefae87c2222f7ce49923e7841faca482
You ask a lot of questions, but I'll give it a shot.
By an interface (C# terminology) I mean an abstract class with no data members.
Nothing specifically like a C# interface exists. A C++ abstract base class comes the closest, but there are differences (for example, you will need to define a body for the virtual destructor).
Thus, such a class only specifies a contract (a set of methods) that sub-classes must implement. My question is: How to implement such a class correctly in modern C++?
As a virtual base class.
Example:
class OutputSink
{
public:
~OutputSink() = 0;
// contract:
virtual void put(std::vector<std::byte> const& bytes) = 0;
};
OutputSink::~OutputSink() = default;
Hence I guess it should be declared with the struct keyword, since it only contains public members anyway.
There are multiple conventions for when to use a structure versus a class. The guideline I recommend (hey, you asked for opinions :D) is to use structures when you have no invariants on their data. For a base class, please use the class keyword.
"A polymorphic class should suppress copying"
Mostly true. I have written code where the client code didn't perform copies of the inherited classes, and the code worked just fine (without prohibiting them). The base classes didn't forbid it explicitly, but that was code I was writing in my own hobby project. When working in a team, it is good practice to specifically restrict copying.
As a rule, don't bother with cloning, until you find an actual use case for it in your code. Then, implement cloning with the following signature (example for my class above):
virtual std::unique_ptr<OutputSink> OutputSink::clone() = 0;
If this doesn't work for some reason, use another signature (return a shared_ptr for example). owner<T> is a useful abstraction, but that should be used only in corner cases (when you have a code base that imposes on you the use of raw pointers).
An interface should consist only of public methods. It should declare [...]. It should [...]. It should be derived using public virtual.
Don't try to represent the perfect C# interface in C++. C++ is more flexible than that, and rarely will you need to add a 1-to-1 implementation of a C# concept in C++.
For example, in base classes in C++ I sometimes add public non-virtual function implementations, with virtual implementations:
class OutputSink
{
public:
void put(const ObjWithHeaderAndData& o) // non-virtual
{
put(o.header());
put(o.data());
}
protected:
virtual void put(ObjectHeader const& h) = 0; // specialize in implementations
virtual void put(ObjectData const& d) = 0; // specialize in implementations
};
thus the abstract base-class always needs to declare a default constructor?! Am I misunderstanding something?
Define the rule of 5 as needed. If code doesn't compile because you are missing a default constructor, then add a default constructor (use the guidelines only when they make sense).
Edit: (addressing comment)
as soon as you declare a virtual destructor, you have to declare some constructor for the class to be usable in any way
Not necessarily. It is better (but actually "better" depends on what you agree with your team) to understand the defaults the compiler adds for you and only add construction code when it differs from that. For example, in modern C++ you can initialize members inline, often removing the need for a default constructor completely.
While the majority of the question has been answered, I thought I'd share some thoughts on the default constructor and the virtual inheritance.
The the class must always have a public (Or at least protected) constructor to assure that sub-classes can still call the super-constructor. Even though there is nothing to construct in the base class, this is a necessity of the syntax of C++ and conceptually makes no real difference.
I like Java as an example for interfaces and super-classes. People often wonder why Java separated abstract classes and interfaces into different syntactical types. As you probably already know though, this is due to the diamond inheritance problem, where two super-class both have the same base class and therefore copy data from the base class. Java makes this impossible be forcing data-carrying classes to be classes, not interfaces and forcing sub-classes to only inherit from one class (not interface which doesn't carry data).
We have following situation:
struct A {
int someData;
A(): someData(0) {}
};
struct B : public A {
virtual void modifyData() = 0;
};
struct C : public A {
virtual void alsoModifyData() = 0;
};
struct D : public B, public C {
virtual void modifyData() { someData += 10; }
virtual void alsoModifyData() { someData -= 10; }
};
When modifyData and alsoModifyData are called on an instance of D, they will not modify the same variable as one might expect due to the compiler which will create two copies of someData for classes B and C.
To counter this problem, the concept of virtual inheritance was introduced. This means that the compiler will not just brute-force recursively build up a derived class from the super-classes members but instead see if the virtual super-classes derive from a common ancestor. Very similarly, Java has the concept of an interface, which is not allowed to own data, just functions.
But interfaces can strictly inherit from other interfaces, excluding the diamond problem to begin with. This is where Java of course differs from C++. These C++ "Interfaces" are still allowed to inherit from data-owning classes, whereas this is impossible in java.
The idea of having a "virtual inheritance", which signals that the class should be sub-classed and that data from ancestors is to be merged in case of diamond inheritance makes the necessity (or at least the idiom) of using virtual inheritance on "Interfaces" clear.
I hope this answer was (although more conceptual) helpful to you!
#include<iostream>
class A {
public:
int a;
protected:
void func() {
std::cout<<"protected member"<<endl;
}
};
class B:public A
{
public:
using A::func; //Isn't this violation of encapsulation?
};
int main(){
B b;
b.func();
return 0;
}
Why the above code runs successfully?
Does it not violate the concept of Encapsulation?
Correct me if I am wrong.
This is an interesting question, and I think it highlights an important and often-overlooked aspect of encapsulation in c++.
My answer is that "yes, encapsulation has been violated, but not where you think". The actual violation was in declaring the method to be protected in the first place.
Your code demonstrates nicely the problem with the protected relationship with subclasses... they can de-protect you with ease. Another way of saying this is that if you're going to make a member protected, you may as well make it public because in reality protected is public if your subclasses want it to be.
What does this mean in practice?
It means that if you make a member function protected, it is forever part of your class's interface. Therefore you must treat is as seriously as you would any other public member function and indeed as if it were a public member function.
Which is to say that it should be as stateless as possible, with as few preconditions as possible and should you change the implementation, the logical effect on the object as a whole must remain unchanged.
The example that you are showing is not a violation of encapsulation, because subclasses are allowed to add public members on top of what they inherit, and they also are allowed to access protected members that they inherit.
In your case, B, a subclass of A, decided to add a new member function called func, whose implementation happens to consist of a single invocation of A::func.
Generally, protected members should be regarded part of interface of your class, along with its public members. Despite the fact that their visibility is limited to subclasses, protected members are not part of the class implementation, because any change to protected members naming or semantics need to be coordinated with changes to all subclasses of the class.
I am learning the concepts of OOPS, and came across private inheritance. From what I've learnt - When a class derives from a base class and letter when the derived class is instantiated, the constructor of the Base class is called first, followed by the constructor of the derived class. So, in the code "A created" would be printed first.
The problem is since the inheritance is private, all the members of A would be private inside B, so how can the constructor of A be called when B is instantiated. Going by this logic, the following code should generate errors, but when I run it, it compiles fine, and gives the output "A created" followed by "B created".
How is this happening? Or am I making some mistake in understanding the concept?
#include <iostream>
using namespace std;
class A{
public:
A(void)
{
cout<<"A created"<<endl;
}
~A()
{
//do nothing
}
void doSomething(void)
{
cout<<"hi";
}
};
class B:private A
{
public:
B(void)
{
cout<<"B created"<<endl;
}
~B()
{
//do nothing
}
};
int main() {
B* myptr = new B();
//myptr->doSomething();
delete myptr;
return 0;
}
B can call public (and protected) methods of A, since A constructor is public B can call it.
Please see following link to better understand c++ private inheritance:
Difference between private, public, and protected inheritance
The access specifier for inheritance limits access to code outside the derived class; think to the base class A as if it were a normal private field:" the outside" can't see it, but B can use it freely from "the inside".
As for the constructor, it's implicitly called by B's constructor, so there's no problem (and, besides, otherwise private inheritance would be unusable).
Still, don't worry too much about private inheritance, it's useful in extremely rare cases (I've never seem it actually used in real life, and for this reason many languages don't even support it), normally composition (using a normal private field) is a better and simpler way.
Here is good short article about private inheritance which illustrates in details what is private inheritance, when it is useful and when it should be avoided in favour of inclusion.
In short:
Inheritance access modifier limits access to basic class properties and methods not for derived class but for code which uses derived class.
This is useful to 'replace' (not 'extend') basic class interface for users of inherited class.
In general it's considered better to include basic class member rather than use private inheritance.
If you need to reuse some methods of basic class which rely on virtual functions and you need to override virtual functions (but you still want to hide part of basic class interface from external code), this is more appropriate case for private inheritance.
Hope this will help.
I'm C++ newbie, and I have many years of experience about OO languages such as C/C#/Objective-C. Now, I'm learning C++.
I saw this C++ code:
class World : public State
{
};
It seems class World inherits the class State publicly.
Public subclassing? It's hard to understand.
What's the concept of this feature?
And when is this useful or required?
The need for the public keyword there is just that for classes defined with the keyword class, the default access modifier (for everything - data members, member functions, and base classes) is private. So
class World : State {};
is the same as:
class World : private State {};
and that's probably not what you want - it means that the base class is only accessible within the class World. Outsiders "don't know" that the inheritance is there at all.
For classes defined with the keyword struct, the default access modifier is public, so you could write:
struct World : State {};
and get something that both looks and behaves a bit like every other language with inheritance. But the struct keyword, and the fact that it defines a class, is really only there for compatibility with C. You won't find many C++ style guides that recommend using it just in order to get the default public accessibility - generally it's used only for classes which are POD, or perhaps only for classes with no member functions at all.
As for why C++ has private inheritance in the first place: for most purposes, private inheritance is a form of composition. Normal composition:
class World {
State state;
public:
void foo() {
state.bar();
state.baz();
and so on
}
};
That is, the class World knows that it's implemented using a State, and the outside world doesn't know how World is implemented.
vs.
class World : private State {
public:
void foo() {
bar();
baz();
and so on
}
};
That is, the class World knows that it's implemented by being a State, and the outside world doesn't know how it's implemented. But you can selectively expose parts of the interface of State by for example putting using State::bar; in the public part of World's definition. The effect is as if you'd laboriously written a function (or several overloads) in World, each of which delegates to the same function on State.
Other than avoiding typing, though, one common use of private inheritance is when the class State is empty, i.e. has no data members. Then if it's a member of World it must occupy some space (admittedly, depending on the object layout this might be space that otherwise would just be padding, so it doesn't necessarily increase the size of World), but if it's a base class then a thing called the "empty base class optimization" kicks in, and it can be zero-size. If you're creating a lot of objects, this might matter. Private inheritance enables the optimization, but the outside world won't infer an "is-a" relationship, because it doesn't see the inheritance.
It's a pretty fine difference - if in doubt just use explicit composition. Introducing inheritance to save typing is all very well until it has some unexpected consequence.
In case
class World: private State
{
};
private inheritance means that all public and protected members of State would be inherited by World and would become private. This seals State inside World. No class that inherits from World will be able access any features of State.
What makes you think that it's private? It says public right there, which means it is publically subclassing.
That aside, what private and protected inheritance do is the same as public inheritance, except that all the member variables are functions are inherited with at least private or protected accessibility. For example, if State had a public member function 'foo()', it would be private in 'World'.
This is rarely used in practice, but it does have purpose. The most common use that I've seen is composition through inheritance. i.e. you want a "has a" relationship rather than an "is a" (that you usually get with public inheritance). By privately inheriting the class, you get all its variables and methods, but you don't expose them to the outside world.
One advantage of using private inheritance for composition comes from the empty base class optimisation (EBCO). Using normal composition, having a member object of an empty class would still use at least 1 byte because all variables must have a unique address. If you privately inherit the object you want to be composed of then that doesn't apply and you won't suffer memory loss.
e.g.
class Empty { };
class Foo
{
int foo;
Empty e;
};
class Bar : private Empty
{
int foo;
};
Here, sizeof(Foo) will probably be 5, but sizeof(Bar) will be 4 because of the empty base class.
The public/protected/private keyword before the name of the ancestor class indicates the desired visibility of members from the ancestor. With private inheritance, the descendant inherits only the implementation from the ancestor, but not the interface.
class A {
public:
void foo();
};
class B : private A {
public:
void bar();
};
void B::bar()
{
foo(); // can access foo()
}
B b;
b.foo(); // forbidden
b.bar(); // allowed
In general, you should use public inheritance because inheritance shouldn't be used for implementation re-use only (which is what private inheritance does).
Why would I want to define a C++ interface that contains private methods?
Even in the case where the methods in the public scope will technically suppose to act like template methods that use the private methods upon the interface implementation, even so, we're telling the technical specs. right from the interface.
Isn't this a deviation from the original usage of an interface, ie a public contract between the outside and the interior?
You could also define a friend class, which will make use of some private methods from our class, and so force implementation through the interface. This could be an argument.
What other arguments are for defining a private methods within an interface in C++?
The common OO view is that an interface establishes a single contract that defines how objects that conform to that interface are used and how they behave. The NVI idiom or pattern, I never know when one becomes the other, proposes a change in that mentality by dividing the interface into two separate contracts:
how the interface is to be used
what deriving classes must offer
This is in some sense particular to C++ (in fact to any language with multiple inheritance), where the interface can in fact contain code that adapts from the outer interface --how users see me-- and the inner interface --how I am implemented.
This can be useful in different cases, first when the behavior is common but can be parametrized in only specific ways, with a common algorithm skeleton. Then the algorithm can be implemented in the base class and the extension points in derived elements. In languages without multiple inheritance this has to be implemented by splitting into a class that implements the algorithm based in some parameters that comply with a different 'private' interface. I am using here 'private' in the sense that only your class will use that interface.
The second common usage is that by using the NVI idiom, it is simple to instrument the code by only modifying at the base level:
class Base {
public:
void foo() {
foo_impl();
}
private:
virtual void foo_impl() = 0;
};
The extra cost of having to write the dispatcher foo() { foo_impl(); } is rather small and it allows you to later add a locking mechanism if you convert the code into a multithreaded application, add logging to each call, or a timer to verify how much different implementations take in each function... Since the actual method that is implemented in derived classes is private at this level, you are guaranteed that all polymorphic calls can be instrumented at a single point: the base (this does not block extending classes from making foo_impl public thought)
void Base::foo() {
scoped_log log( "calling foo" ); // we can add traces
lock l(mutex); // thread safety
foo_impl();
}
If the virtual methods were public, then you could not intercept all calls to the methods and would have to add that logging and thread safety to all the derived classes that implement the interface.
You can declare a private virtual method whose purpose is to be derivated. Example :
class CharacterDrawer {
public:
virtual ~CharacterDrawer() = 0;
// draws the character after calling getPosition(), getAnimation(), etc.
void draw(GraphicsContext&);
// other methods
void setLightPosition(const Vector&);
enum Animation {
...
};
private:
virtual Vector getPosition() = 0;
virtual Quaternion getRotation() = 0;
virtual Animation getAnimation() = 0;
virtual float getAnimationPercent() = 0;
};
This object can provide drawing utility for a character, but has to be derivated by an object which provides movement, animation handling, etc.
The advantage of doing like this instead of provinding "setPosition", "setAnimation", etc. is that you don't have to "push" the value at each frame, instead you "pull" it.
I think this can be considered as an interface since these methods have nothing to do with actual implementation of all the drawing-related stuff.
Why would I want to define a C++
interface that contains private
methods?
The question is a bit ambiguous/contradictory: if you define (purely) an interface, that means you define the public access of anything that connects to it. In that sense, you do not define an interface that contains private methods.
I think your question comes from confusing an abstract base class with an interface (please correct me if I'm wrong).
An abstract base class can be a partial (or even complete) functionality implementation, that has at least an abstract member. In this case, it makes as much sense to have private members as it makes for any other class.
In practice it is rarely needed to have pure virtual base classes with no implementation at all (i.e. base classes that only define a list of pure virtual functions and nothing else). One case where that is required is COM/DCOM/XPCOM programming (and there are others). In most cases though it makes sense to add some private implementation to your abstract base class.
In a template method implementation, it can be used to add a specialization constraint: you can't call the virtual method of the base class from the derived class (otherwise, the method would be declared as protected in the base class):
class Base
{
private:
virtual void V() { /*some logic here, not accessible directly from Derived*/}
};
class Derived: public Base
{
private:
virtual void V()
{
Base::V(); // Not allowed: Base::V is not visible from Derived
}
};