C++: where to place constructor in inheritance chain? - c++

I have following dilemma:
I have a full abstract class. Each inheriting class will need 3 same parameters. Each of them will additionally need other specific parameters.
I could:
1) implement a common constructor for initializing 3 common parameters in my base class, but then I have to make non-abstract getters for corresponding fields (they are private).
OR
2) leave my base class abstract and implement constructors in inherited classes, but then I have to make it in each class fields for common parameters.
Which is a better approach? I don't want to use protected members.

An abstract class is one who has at least one pure virtual (or, as you call it, abstract) function. Having non-abstract, non-virtual functions does not change the fact that your class is abstract as long as it has at least one pure virtual function. Go for having the common functionality in your base class, even if it is abstract.

One way to avoid code duplication without polluting your abstract interface with data members, is by introducing an additional level of inheritance:
// Only pure virtual functions here
class Interface {
public:
virtual void foo() = 0;
};
// Things shared between implementations
class AbstractBase : public Interface {
};
class ImplementationA : public AbstractBase {
};
class ImplementationB : public AbstractBase {
};

If your class looks like this, a pure abstract class:
class IFoo {
public:
virtual void doThings() = 0;
}
class Foo {
public:
Foo(std::string str);
void doThings() override;
}
The value your inheritance has is to provide you with the oppurtunity to subsitute Foo with another at runtime, but hiding concrete implementations behind interfaces. You can't use that advantage with Constructors, there's no such thing as a virtual constructor (that's why things like the Abstract Factory Pattern exist). All your implementations of Foo take a std::string and all your implementations of doThings use that string? Great, but that's a coincidence not a contract and doesn't belong in IFoo.
Lets talk about if you've created concrete implementations in IFoo, so that it's a abstract class and not a pure abstract class (IFoo would be a bad name now btw). (*1) Lets assume using inheritance to share behaviour was the correct choice for you class, which is sometimes true. If the class has fields that need to be initialised create a protected constructor (to be called from every child implementation) and remove/ommit the default one.
class BaseFoo {
private:
std::string _fooo;
protected:
BaseFoo(std::string fooo) : _fooo(fooo) {}
public:
virtual void doThings() = 0;
std::string whatsTheBaseString() { return _fooo;}
}
Above is the way you correctly pass fields needed by a base class from the child constructor. This is a compile time guarantee that a child class will 'remember' to initialize _fooo correctly and avoids exposing the actual member fooo to child classes. Trying to initialize _fooo in all the child constructors directly would be incorrect here.
*1) Quickly, why? Composition may be a better tool here?.

Related

Is it dangerous to create pure virtual function of a virtual function?

Let us suppose that we have an abstract class NonEditableSuperBase from which we create another abstract class MyBase.
The first class NonEditableSuperBase has a virtual function (non pure virtual). However, I want to force that if someone creates a class that derives from MyBase, he/she must provide an implementation to the mentioned function.
Hence, my idea is to define the function as pure virtual in MyBase.
My question: Is it a bad idea given that it was just virtual in NonEditableSuperBase?
Example:
//NonEditableSuperBase.h
class NonEditableSuperBase
{
...
public:
virtual int someMethod(); //It has an implementation, suppose {return 42;}
};
//MyBase.h
class MyBase: public NonEditableSuperBase
{
public:
explicit MyBase();
virtual ~MyBase() = default;
virtual int someMethod() = 0; //I make it pure virtual
};
//MyBase.cpp
MyBase::MyBase() : NonEditableSuperBase() { }
//Now someone creates a derived class from MyBase.
class SuperDerived : public MyBase
{
public:
explicit SuperDerived();
int someMethod(); //The user must create an implementation of the function
};
Update:
As an example, in my case I want to create some derived classes from the QAbstractTableModel class of the Qt framework. To reuse some code I want to create an intermediate abstract class.
QAbstractTableModel <- MyAbstractModel <- MyModelA (or MyModelB ... etc).
However, I want to ensure that the models (MyModelA, MyModelB) re-implement some of the virtual functions of QAbstractTableModel (like the ::index() function) because some of the additional methods of MyAbstractModel requires specific implementations of the primer functions.
From ISO IEC 14882 2014:
§ 10.4 says:
5 [ Note: An abstract class can be derived from a class that is not abstract, and a pure virtual function may
override a virtual function which is not pure. —end note ]
So It's perfectly possible to do that.
Example of use case:
You can have a basic type, that is implemented as a concrete type (base class). Now, for subtypes, we might be in a need of further additional information. So, we can have an abstract intermediate object to meet our needs.
[I'm assuming that the intent was for MyBase to publicly derive from NonEditableSuperBase, which is not what the code sample in the question actually does.]
It doesn't seem inherently dangerous, but consider that a class like SuperDerived that derives from MyBase could explicitly choose to use the NonEditableSuperBase implementation.
class SuperDerived : public MyBase {
public:
using NonEditableSuperBase::someMethod;
// Or, explicitly:
// int someMethod() override { return NonEditableSuperBase::someMethod(); }
};
This satisfies the pure-virtual requirement imposed by MyBase but acts exactly as if MyBase didn't have that requirement. You've made the author of SuperDerived do something, but you haven't actually prevented them from using the ultimate base class's implementation.

Why in C++ 'virtual' and '=0' is both needed to describe a method is abstract?

As it is explained in The C++ programming language:
virtual void push(char c) = 0;
virtual void pop() = 0;
The word virtual means 'may be redefined later in a class derived from this one'
The =0 syntax says that some class derived from Stack must define the function.
So why =0 symbol is needed? Does it means that a derived class must define this function, and that's to say when there is no =0, some derived classes are not forced to define this method?
I'm confusing about this, need some help.
Your thoughts were right.
So why =0 symbol is needed? Does it means that a child class must
define this function, and that's to say when there is no =0, some
child classes are not forced to define this method?
Basically you can:
Make a method non-virtual
This doesn't allow any class deriving from the class that implements the method (through either public or protected) to change the method's behavior.
Make a method virtual
This allows (but doesn't enforce) any class deriving from the class that implements the method (through either public or protected) to change the behavior of the method in the base class. You don't even have to call the original base class method anymore so you can make severe changes if needed.
Make a method pure virtual ( virtual = 0 )
This enforces that any class deriving from the class that implements the method (through either public or protected) to implement some kind of behavior/body for this method. If the deriving class does not provide an implementation then this class will instantly become abstract itself. This allows to omit the behavior/body of the method in the base class and because of this it is not allowed to directly instantiate a class that has one or more pure virtual methods (abstract class).
So why =0 symbol is needed?
Consider the following:
struct foo
{
virtual void some() const { cout << "foo" << endl; }
};
struct bar : public foo
{
virtual void some() const { cout << "bar << endl; }
};
struct baz : public foo
{
}
Suppose you have a pointer foo *p pointing to some object, and you call p->some().
If p points to a bar object, it will print "bar".
If p points to a baz object, it will print "foo".
In some cases, this might not be what you want. You might want to specify that any derived class needs to override it. The =0 does that.
The purpose of an abstract class (those classes have pure virtual method, =0) is to provide an appropriate base class from which other classes can inherit. Abstract classes cannot be used to instantiate objects and serves only as an interface.
Thus, if a subclass of an abstract class needs to be instantiated, it has to implement each of the virtual functions, which means that it supports the interface declared by the abstract class.
That is the base concept for interface.
In short, it a way to be sure a derivative class will implement those methods from the base class.
So why =0 symbol is needed?
Virtual function with sequence = 0 is known as pure virtual function, (the sequence = 0 is known as pure-specifier), it makes the class an abstract class, which can't be instantiated. For the derived classes, if they want to make it possible to be instantiated, they have to implement the pure virtual function.
No objects of an abstract class can be created. Abstract types cannot be used as parameter types, as function return types, or as the type of an explicit conversion. Pointers and references to an abstract class can be declared.
For example,
class Stack {
virtual void push(char c) = 0;
};
...
Stack s; // Fail, Stack is an abstract class
and if
class Stack {
virtual void push(char c);
};
...
Stack s; // Fine, if you won't call `push()` on it.
First consider what is the reason to use virtual methods.
1.Interface(polymorphism).
Interface in C++ is a pure virtual class, which means, that all of its methods are pure virtual (like these two you've mentioned above), it has an virtual destructor and has no constructor (it's obvious, because we can't create its instances). It also shouldn't have any data.
Let's define an interface (pure abstract class in C++):
class Interface
{
public:
virtual ~Interface(){}
virtual void somePublicMethod() = 0;
};
And define the class, which is an implementation of interface:
class Implementation : public Interface
{
public:
~Implementation() override {}
void somePublicMethod() override {}
};
If you define another pure virtual method in interface:
virtual void anotherPublicMethod() = 0;
And you don't override it in implementation you will receive compilation error, when you will declare object of Implementation type, because real Implementation object must have definitions (bodies) for all derived methods.
Yo can also define default behavior of some interface's method:
void Interface::somePublicMethod()
{
//define default behavior here
}
And call it in derived class:
void Implementation::somePublicMethod()
{
Interface::somePublicMethod();
}
How interface is used in polymorphism you will read in other topics.
2."Ordinary" Inheritance.
In "ordinary" inheritance you should use virtual methods instead of pure virtual ones, because you want to have instances of both Base class and Derived class(es). Virtual methods only indicates, that they could be overridden in derived class(es).
Conclusion
In general, if you want to have an instance of any class, this class must have all methods defined (so the must have bodies and it's obvious that they mustn't be pure virtual).

More methods in derived classes than 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.

Should private inheritance be used when there are no virtuals?

In C++, if I have a class Base which is a private base class of Derived but Base has no virtual functions, would it be cleaner to instead replace having inheritance with encapsulation in class Encapsulate? I imagine the only benefit to inheritance in this case would be that the base class can be accessed directly in the derived class as opposed to through memberVariable. Is one or the other practice considered better, or is it more of a personal style question?
class Base {
public:
void privateWork();
// No virtual member functions here.
};
class Derived : Base {
public:
void doSomething() {
privateWork();
}
};
class Encapsulate {
Base memberVariable;
public:
void doSomething() {
memberVariable.privateWork()
}
};
Remember that inheritance models "Liskov substitution": Foo is a Bar if and only if you can pass a Foo variable to every function expecting a Bar. Private inheritance does not model this. It models composition (Foo is implemented in terms of Bar).
Now, you should pretty much always use the second version, since it is simpler and expresses the intent better: it is less confusing for people who don't know about it.
However, sometimes, private inheritance is handy:
class FooCollection : std::vector<Foo>
{
public:
FooCollection(size_t n) : std::vector<Foo>(n) {};
using std::vector<Foo>::begin;
using std::vector<Foo>::end;
using std::vector<Foo>::operator[];
};
This allows you to reuse some of the functionality of vector without having to forward manually the 2 versions (const + non const) of begin, end, and operator[].
In this case, you don't have polymorphism at all: this is not inheritance, this is composition is disguise; there is no way you can use a FooCollection as a vector. In particular, you don't need a virtual destructor.
If there are no virtual functions, then inheritance should not be used in OO. Note this does not mean that it must not be used, there are a few (limited) cases where you might need to (ab)use inheritance for other purposes than OO.

Virtual Inheritance Confusion

I'm reading about inheritance and I have a major issue that I haven't been able to solve for hours:
Given a class Bar is a class with virtual functions,
class Bar
{
virtual void Cook();
};
What is the different between:
class Foo : public Bar
{
virtual void Cook();
};
and
class Foo : public virtual Bar
{
virtual void Cook();
};
? Hours of Googling and reading came up with lots of information about its uses, but none actually tell me what the difference between the two are, and just confuse me more.
Functionality wise there is not much difference between the 2 versions. With the case of virtual inheritance, every implementation generally adds a (vptr like) pointer (same as in the case of virtual functions). Which helps to avoid multiple base class copies generated due to multiple inheritance (the diamond inheritance problem)
Also, virtual inheritance delegates the right to call the constructor of its base class. For example,
class Bar;
class Foo : public virtual Bar
class Other : public Foo // <--- one more level child class
So, now Bar::Bar() will be called directly from Other::Other() and also will be placed at the first place among other base classes.
This delegation feature helps in implementing a final class (in Java) functionality in C++03:
class Final {
Final() {}
friend class LastClass;
};
class LastClass : virtual Final { // <--- 'LastClass' is not derivable
...
};
class Child : public LastClass { // <--- not possible to have object of 'Child'
};
Virtual inheritance is only relevant if classes are to inherit from
Foo. If I define the following:
class B {};
class L : virtual public B {};
class R : virtual public B {};
class D : public L, public R {};
Then the final object will only contain one copy of B, shared by both
L and R. Without the virtual, an object of type D would contain
two copies of B, one in L, and one in R.
There is some argument that all inheritance should be virtual (because
in the cases where it makes a difference, that is what you want most of
the time). In practice, however, virtual inheritance is expensive, and
in most cases, not necessary: in a well designed system, most
inheritance will simply be of a concrete class inheriting from one or
more "interfaces"; such a concrete class is usually not designed to be
derived from itself, so there is no problem. But there are important
exceptions: if, for example, you define an interface, and then
extensions to the interface, the extensions should inherit virtually
from the base interface, since a concrete implementation could want to
implement several extensions. Or if you are designing mixins, where
certain classes only implement part of the interface, and the final
class inherits from several of these classes (one per part of the
interface). In the end, the criteron as to whether to inherit virtually
or not isn't too difficult:
if the inheritance isn't public, it probably shouldn't be virtual
(I've never seen an exception), otherwise
if the class is not designed to be a base class, there's no need for
virtual inheritance, otherwise
the inheritance should be virtual.
There are a few exceptions, but the above rules err on the side of
safety; it's usually "correct" to inherit virtually even in cases where
the virtual inheritance isn't necessary.
One final point: a virtual base must always be initialized by the most
derived class, not the class that directly inherits (and declares that
the inheritance is virtual). In practice, however, this is a non-issue.
If you look at the cases where virtual inheritance makes sense, it is
always a case of inheriting from an interface, which will contain no
data, and thus have (only) a default constructor. If you find yourself
inheriting virtually from classes with constructors which take
arguments, it's time to ask some serious questions about the design.
In this case, no difference. Virtual inheritance is related to sharing superclass subobjects instances by derived classes
struct A
{
int a;
};
struct B : public virtual A
{
int b;
}
struct C : public virtual A
{
int c;
};
struct D : public B, public C
{
};
There's a single copy of the member variable a in the instance of D; If A was not a virtual base class, there would be two A subobjects in instance of D.
Virtual function is a function that will probably have different implementation in derived class (although it's not a must).
In your last example is virtual inheritance. Imagine a case where you have two classes (A and B) derived from a base class (let's call it 'Base'). Now imagine a third class C derived from A and B. Without virtual inheritance, the C would contain two copies of 'Base'. That could lead to ambiguity while compiling. The important thing in virtual inheritance is that the parameters for the 'Base' class constructor (if any) MUST be provided in the class C, because such calls from A and B will be ignored.