I've a question regarding a concept. First, I'm a mechanical engineer and not a programmer, thus I have some C++ knowledge but not much experience. I use the finite element method (FEM) to solve partial differential equations.
I have a base class Solver and two child linSolver, for linear FEM, and nlinSolver for non-linear FEM. The members and methods that both children share are in the base class. The base class members are all protected. Thus using inheritance makes the child classes "easy to use", like there weren't any inheritance or other boundaries. The base class itself, Solver, is incomplete, meaning only the children are of any use to me.
The concept works actually pretty good - but I think that having an unusable class is a bad design. In addition I read that protected inheritance is not preferred and should be avoided if possible. I think the last point don't really apply to my specific use, since I will never use it allow and any attempt to do so will fail (since it is incomplete).
The questions are:
Is it common to use inheritance to reduce double code even if the base class will be unusable?
What are alternatives or better solutions to such a problem?
Is protected inheritance really bad?
Thank you for your time.
Dnaiel
Having "unusable" base classes is actually very common. You can have the base class to define a common interface usable by the classes that inherits the base-class. And if you declare those interface-functions virtual you can use e.g. references or pointers to the base-class and the correct function in the inherited class object will be called.
Like this:
class Base
{
public:
virtual ~Base() {}
virtual void someFunction() = 0; // Declares an abstract function
};
class ChildA : public Base
{
public:
void someFunction() { /* implementation here */ }
};
class ChildB : public Base
{
public:
void someFunction() { /* other implementation here */ }
};
With the above classes, you can do
Base* ptr1 = new ChildA;
Base* ptr2 = new ChildB;
ptr1->someFunction(); // Calls `ChildA::someFunction`
ptr2->someFunction(); // Calls `ChildB::someFunction`
However this will not work:
Base baseObject; // Compilation error! Base class is "unusable" by itself
While the (working) example above is simple, think about what you could do when passing the pointers to a function. Instead of having two overloaded functions each taking the actual class, you can have a single function which takes a pointer to the base class, and the compiler and runtime-system will make sure that the correct (virtual) functions are called:
void aGlobalFunction(Base* ptr)
{
// Will call either `ChildA::someFunction` or `ChildB::someFunction`
// depending on which pointer is passed as argument
ptr->someFunction();
}
...
aGlobalFunction(ptr1);
aGlobalFunction(ptr2);
Even though the base-class is "unusable" directly, it still provides some functionality that is part of the core of how C++ can be (and is) used.
Of course, the base class doesn't have to be all interface, it can contain other common (protected) helper or utility functions that can be used from all classes that inherits the base class. Remember that inheritance is a "is-a" relationship between classes. If you have two different classes that both "is-a" something, then using inheritance is probably a very good solution.
You should check the concept of Abstract class.
It's designed to provide base class that cannot be instantiated.
To do so you provide at least one method in the base class like this
virtual void f()=0;
Each child have to override the f function (or any pure virtual function from the base class) in order to be instantiable.
Don't think of the BaseClass as a class in its own right, but as an interface contract and some implementation help. Therefore, it should be abstract, if neccessary by declaring the dtor pure virtual but providing an implementation anyway. Some OO purists may frown upon any non-private element, but purity is not a good target.
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!
I couldn't find examples of is-a relationship without virtual functions. Is a following pattern ok?
class Base {
public:
void doSomethingWithX() {/*implementation here*/}
protected:
~Base(){}
private:
int x_;
};
class Derived : public Base {
//Add some other functionality but inherit doSomethingWithX and its implementaion
public:
void doSomethingWithY();
~Derived(); //And document that nobody should inherit further from this class.
private:
int y_;
};
foo(Base* ptr) {
//Do something via Base interface
}
Derived d;
foo(&d);
Edit: I was asked to clarify what I mean by "is this pattern ok".
Does this kind of inheritance satisfies what is usually needed from is-a relationship? Liskov substitution principle etc.
Is it safe to use Derived objects via pointer to Base? (or I miss some problem here).
I'm asking this because there is often written that base class destructor should be either public and virtual or protected and non-virtual. But I never met real examples of public inheritance without non-virtual functions.
It's okay for what you're doing here; You can pass a pointer to Derived and it can bind to a pointer of Base just fine. It's not possible to say whether it satisfies the Liskov subtitution principle because we do not know the invariants of your classes.
Just recognize that without any virtual functions, you cannot use polymorphism. This goes beyond simply overriding function behavior; you'll never be able to perform a dynamic_cast of a pointer to Base to a pointer to Derived.
Additionally, if nobody should derive from Derived, then mark it final, which is available since C++11
There are two types of polymorphism, both implementable in C++: static and dynamic. The latter is what you get with virtual functions and pointers to base classes, in which the behaviour is specialized depending on the real type of object pointed to.
The former can be achieved by writing a template, in which your template type is assumed to have certain interfaces. The compiler will then enforce that when instantiating the template, at compile time. You can provide additional enforcement using SFINAE and/or static_asserts to ensure the type used "is a" or rather conforms to the templated interface used by your code. Note there is not really a straightforward way of defining this interface as with a base interface class, aside from the aforementioned methods.
Note that static polymorphism is what you get at compile time. No dynamically chosen types at runtime. You'll need some form of base class for that.
I searched for this, but I feel I'm not finding the answer I'm after. So, simple version and hopefully someone can just say "here's how" and I'll be on my way :)
Essentially I want this:
class BaseObject
{
public:
BaseObject();
~BaseObject();
virtual bool FunctionX() =0;
virtual bool FunctionY() =0;
};
class ObjectA : BaseObject
{
public:
ObjectA();
~ObjectA();
bool FunctionX();
bool FunctionY();
bool FunctionZ();
};
.. same for ObjectB as above ..
...
vector<BaseObject*> myList;
ObjectA a;
ObjectB b;
myList.push_back((BaseObject*)&a);
myList.push_back((BaseObject*)&b);
myList.back()->FunctionX();
I know the code above is wrong, I'm just trying to get the overall concept over.
What I need:
A base class that defines functions that MUST be present in classes that inherit from it.
The ability to store the classes that inherit from it all in the same vector (cast as the base class).
The vector to know it can call the base classes defined functions.
The classes to be able to have their own, additional functions that the vector/base class do not need to be aware of.
I just noticed, you're deriving privately. BaseObject is a private base class of ObjectA. When you omit the inheritance specifier, you get private inheritance by default. Change the ObjectA declaration to
class ObjectA : public BaseObject...
Otherwise, code outside of the ObjectA scope is not allowed to know that ObjectA is-a BaseObject.
Your code is almost right. It misses the virtual for BaseObject's destructor, however, which will invoke undefined behaviour (e.g. crashes) in any typical usage scenario. This is the correct declaration:
virtual ~BaseObject();
Another thing you should consider is making your public functions non-virtual and your virtual functions private, with the public functions delegating to the private ones (called Non-Virtual Interface Idiom by Herb Sutter).
A few more things:
A base class that defines functions that MUST be present in classes
that inherit from it.
You won't be able to achieve this, at least in the literal sense, by any normal means. A class can derive from your abstract class but remain itself abstract by not defining your pure virtual functions.
The ability to store the classes that inherit from it all in the same
vector
Mind the difference between "class" and "object". A vector doesn't store classes but objects. In C++, classes cannot be used as objects (which is different in Java, for example). To "store classes" implies something like type lists in advanced template metaprogramming, a technique not related at all to your problem.
(cast as the base class).
You do not need to cast from subclass to base class.
I would like to ask a question about programming style in this case of derived class:
class A
{
public:
virtual foo1()=0;
}
class B: public A
{
public:
virtual foo1();
virtual foo2();
}
class C: public A
{
public:
virtual foo1();
}
int main() {
B mB();
C mC();
mB.foo2() //OK!
mC.foo2() // obviously, it is not correct
return 0;}
Therefore, should a derived class have less or equal public methods than the abstract base class?
If the derived classes require more methods, should these be private?
Derived classes will almost always have more public functions than base classes. This is the point of inheritance: you can define an abstract base class which only outlines the basic behavior of a variable, then derived classes can expand upon this basic behavior for specific cases.
An inherited class is always a specialization of the base class. It implements more specific functions (and usually more functions all together). In you're example, you're expecting two different specializations to behave the same way outside of the behavior defined by the base class. (foo2 is not defined in A). That's where the problem lies. If you need to define common behavior outside of A, the solution would be to create an intermediate class.
class Intermediate : public A
{
public:
virtual foo1()=0;
virtual foo2()=0;
}
class B: public Intermediate
{
public:
virtual foo1();
virtual foo2();
}
Now any class which can implement foo2 should extend Intermediate, and any function which requires functionality foo2 should ask for a variable with at least type Intermediate.
There is nothing wrong with this class structure. There is nothing wrong with a derived class having more methods than the parent class-- it's quite commonplace. The line mC.foo2(); is just wrong, and that is not the fault of the classes.
A derived class must at least implement ALL abstract methods from the base class. This is the minimum. If you do add other methods, members or whatever is up to you.
But it would be not very smart to derive from the class and add nothing, because this is not what inheritance is for (at least IS-A-relationships). If you go for private inheritance it might be different.
In nearly ALL projects I've worked on, we have had baseclasses that have less functionality than the derived class - in extreme cases, the baseclass may even just have nearly no functionality, but the derived class has dozens of functions and a half a dozen member variables.
This is exactly what derived classes are meant to do.
Obviously, you need to KNOW what kind of derived class you have, and only use the derived classes "extra" functions when they are available.
I have an abstract class with a couple pure virtual functions, and one of the classes I derive from it does not use one of the pure virtual functions:
class derivative: public base
{
public:
int somevariable;
void somefunction();
};
anyways, when I try to compile it, I get an error (apparently, a class is still considered abstract if derive from an abstract class and don't override all pure virtual functions). Anyways, it seems pointless to define a function
int purevirtfunc(){return 0;}
just because it needs to be defined through a technicality. Is there anyway to derive a class from an abstract class and not use one of the abstract class's pure virtual functions?
If your derived class doesn't "use" the base class pure virtual function, then either the derived class should not be derived from the base, or the PVF should not be there. In either case, your design is at fault and needs to be re-thought.
And no, there is no way of deleting a PVF.
A pure virtual class is an interface, one which your code will expect to be fulfilled. What would happen if you implemented that interface and didn't implement one of the methods? How would the code calling your interface know that you didn't implement the method?
Your options are:
Implement the method as you describe (making it private would indicate that it shouldn't be used).
Change your class hierarchy to take into consideration the design change.
The purpose of deriving from abstract classes is that external code can use the abstract class and expect that all functions have been implemented properly. Being able to unimplement a method would defeat this purpose, making the code uncompilable. You're free to throw an exception, if you so choose, however.
It's not a technicality at all. If your derived class does not exhibit all of the behavior of the parent, it should not be derived from the parent. This is a major design smell, and you probably need some design refactoring.
When you inherit from a class that has pure virtual functions, you MUST implement those functions. If you don't, then your derived class is also abstract, and you can't create an object of the derived class.
No. Either provide a default implementation in the base class or a simple implementation in the derived class, as you suggested.
There were already good answers, but if you want more info from the theoretical OO design side, check out the Liskov substitution principle.
Allowing this wouldn't make any sense. What would happen if you called the function without an implementation? A runtime error (that would be silly)? You could argue that it could a compile time error in some cases, but this is not possible if the exact type is not known (e.i. you pass a pointer to an instance of the derived class to a function).
As many people have already stated, it sounds like either the base method shouldn't be pure virtual or you should rethink whether your derived class really ISA base.
However, it is possible to provide an implementation for the pure virtual method in the base class. This can act like a default implementation for derived classes, but you still require the derived class to choose the base class's implementation explicity.
I don't know if that will help you with your problem or not.
No, there isn't. The convention in late bound languages when this situation occurs (as it legitimately might, but consider your design to see whether this method can be moved elsewhere, perhaps to its abstract class), is to raise an exception, and make sure that users of that method know that some implementations may raise that exception.
Seems i faced with the same problem, when trying to hide method getVertex() in derived class.
Maybe it's help.
class Body2D
{
public:
virtual ~Body2D() = default;
virtual double getCenter() const = 0;
virtual double getVertex() const = 0;
};
class Ellipse : public Body2D
{
public:
Ellipse(){};
double getCenter() const override{};
private:
double getVertex() const override{};
};
Couldn't you just do
class Foo {
public:
virtual void foo() = 0;
};
class Bar {
public:
virtual void foo() = delete;
};