Class with mix of pure virtual and virtual methods - c++

I created an abstract class which has a set of pure virtual methods only. There are 3 different classes which have concrete implementations of these methods.
Now after writing above structure, I found that some of the methods in the derived classes have identical implementations. So, I moved to the logic to my base class for these functions and made them virtual instead of pure virtual. Now, the implementations do not need to repeat in the derived classes. This compiles and executes fine.
My base class is a mixture of pure virtual and virtual methods, is it a good design approach to follow a structure like this?

It's absolutely fine, although a pattern does seem to have emerged where you would put all and only your pure virtual functions in a class to be regarded as more of an interface.
You would then define a class that implements the "common" parts of that interface, and have your 3 classes inherit from that class.
Over time, it seems that this lends itself to code that is more scalable and easier to maintain.
Java, out of interest, pretty much forces the use of this pattern.

It depends on the relationships between the classes, obviously. In other words, it is a design or implementation choice (i.e. up to you, as long as you can justify it sensibly). Technically, there is nothing preventing a class from having a mix of virtual, pure virtual, non-virtual, and static member functions.
If two derived classes override an inherited virtual function and implement it in the same way, then - yes - I would seriously consider providing that function into the base class. However, there are more questions I would ask - such as whether it makes sense for ALL derived classes to default to that implementation of the function. From a code reuse perspective, such a thing might make sense. From a design perspective, it may not.
That said, if it makes sense to treat a particular implementation of a function as a "default" (i.e. all derived classes default to using that, unless they override that function) then there is no harm in placing that definition in a base class.
As a crude example where what you suggest wouldn't make sense, consider this
class Aircraft
{
public:
virtual void Manoeuvre() = 0;
};
class Hornet : public Aircraft // F/A-18 hornet fighter aircraft
{
public:
void Manoeuvre();
};
class Tomcat : public Aircraft // F-14 tomcat fighter aircraft
{
public:
void Manoeuvre();
};
Let's say that, because of the fidelity of our modelling, that both derived classes had the same Manoeuvre() functions - they are both supersonic fighter aircraft (so will probably employ similar style of manoeuvre, albeit with different parameterisation). However, that is not sufficient to move their Manoeuvre() function to the base class, because there are aircraft that are not supersonic fighters, such as
class Hercules : public Aircraft // C-130 hercules cargo plan
{
public:
void Manoeuvre();
};
In this case, it does not make sense for a Hercules to inherit manoeuvring capability of a supersonic fighter, or vice versa. So it doesn't make sense for this to be supplied by the Aircraft class.
In this case, I might consider introducing intermediate classes, such as Fighter (which could be a common base of Hornet and Tomcat, but not Hercules) and - if I sought to represent multiple types of cargo aircraft - possibly a CargoPlane to be a common base for those. Then both Fighter and CargoPlane might derive from Aircraft, but Aircraft does not supply functionality that only makes sense to some aircraft types.
Incidental comment: although some people claim otherwise, there is nothing in C++ preventing a pure virtual function from having a definition (implementation). The meaning is that the function MUST be overridden by derived classes, but there is a default definition (which can be explicitly called by functions in derived classes) provided by the base class.

Yes, that is fine. However: If these are all the classes you have, there's no need to make the base class implementations virtual.

Related

why we need interface or pure virtual function in c++

why we need interface ( pure virtual function or abstract class) in c++?
Instead of having abstract class, Can we have a base class with virtual function defined in it, and override that virtual function in derived class.
what would be the advantage and disadvantage with the above approach ( except we can create the object of the base class)?
Pure virtual functions are for when there's no sensible way to implement the function in the base class. For example:
class Shape {
public:
virtual float area() const = 0;
};
You can write derived classes like Circle and Rectangle that implement area() using the specific formulas for those kinds of shapes. But how would you implement area() in Shape itself, if it weren't pure virtual? How do you compute the area of a shape without even knowing what kind of shape it is?
If your function can be implemented (in a useful way) in the base class, then go ahead and implement it. Not all base classes need to be abstract. But some of them just inherently are abstract, like Shape.
Pure virtual functions is your way of telling the users of your class that they cannot use the class on its own, without inheriting from it.
Obviously, you can do what you describe, and the system is going to compile and work as expected. However, an pure virtual function is not a construct for the compiler; it is for humans who read your code. It is with this construct that you tell the readers of your code that they must inherit from your class, because the class is not designed to be instantiated on its own.
You use pure virtual functions in situations when there is no reasonable default implementation for a function. This tells people who implement your class that they must provide certain functionality, and the compiler helps them in detecting situations when they forgot to provide an implementation.
If, on the other hand, you provide a default implementation for a virtual function that should be implemented by a subclass, and then the users of your class library forget to provide an implementation, the problem would not be detected until run-time.
An interface give you the ability to specify a set of behaviors that
all classes that implement the interface will share in common.
Consequently, we can define variables and collections (such as arrays)
that don't have to know in advance what kind of specific object they
will hold, only that they'll hold objects that implement the
interface.
Here
As others have said, an interface is a contractual obligation to implement certain methods, properties and events [...] That's a sufficiently awesome benefit to justify the feature.
and here
(please refer to these very good explanations)

How to declare a class explicity abstract?

I am looking at the following:
http://publib.boulder.ibm.com/infocenter/lnxpcomp/v8v101/index.jsp?topic=%2Fcom.ibm.xlcpp8l.doc%2Flanguage%2Fref%2Fcplr142.htm
and it says an abstract class in C++ contains a pure virtual function. However, surely this does not mean to create an abstract class all I do is insert a pure virtual function? Couldn't I have the situation where I have a concrete class which doesn't provide an implementation for one particular function and therefore makes it abstract, forcing derived classes to provide the implementation? This wouldn't make the class abstract though?
So how do I differentiate between "this is an abstract class" and "this is a concrete class with one pure virtual function"?
A class is extactly then abstract when it has one or more pure virtual function. If you write a (base) class, wich has all functions implemented, and thus can be instantiated, but it misses a vital function, then it is simply wrong design of your class.
Your base class wouldn't be complete in this case and the pure virtual uninmplemented function should be added, which makes it an abstract class then.
If you have a derived class, which derives from an abstract class, and doesn't implement all functions from the base class, then it is in turn also abstract. In this case, it wouldn't need a pure virtual function itself, because it is abstract by inheritance.
There is no abstract keyword in C++, like in Java to indicate that a class is abstract.
As already stated above, an abstract class in C++ is, by definition, a class which has at least one pure virtual function. The class being abstract means that you can't make instances of it (only of "concrete" classes derived from it), which protects you from calling the "unexistent" pure virtual functions (although technically you can still call them from base class constructor/destructor and get a nasty runtime crash).
There are no explicit "interface" kind of classes in C++, so you are free to provide implementation for some functions in any classes as you wish, regardless of whether the class is already abstract due to some other function being pure virtual.
On a side note, I'd still like to point out one way to make your class abstract without actually making any "real" methods pure virtual. It is enough to make the class destructor pure virtual (note that it is generally a good idea for the destructor of any polymorphic class to be virtual anyway). A minor gotcha here is that in this particular case (only for destructor), you will still have to provide an implementation for it for the linker to be happy. It may look like this:
class A // abstract class
{
public:
virtual ~A() = 0 {} // destructor is pure virtual, but still needs a body
};
class B : public A {}; // concrete class deriving from an abstract class
Also note that in this particular case, class B does not have to explicitly implement its own destructor to become concrete, so, if you'd like it to be abstract too, you'll have to repeat the same trick again (or add some other pure virtual methods to B).

Is it a good convention to virtually inherit from pure virtual (interface) classes?

I often use pure virtual classes (interfaces) to reduce dependencies between implementations of different classes in my current project. It is not unusual for me to even have hierarchies in which I have pure virtual and non-pure virtual classes that extend other pure virtual classes. Here is an example of such a situation:
class Engine
{ /* Declares pure virtual methods only */ }
class RunnableEngine : public virtual Engine
{ /* Defines some of the methods declared in Engine */ }
class RenderingEngine : public virtual Engine
{ /* Declares additional pure virtual methods only */ }
class SimpleOpenGLRenderingEngine : public RunnableEngine,
public virtual RenderingEngine
{ /* Defines the methods declared in Engine and RenderingEngine (that are not
already taken care of by RunnableEngine) */ }
Both RunnableEngine and RenderingEngine extend Engine virtually so that the diamond problem does not affect SimpleOpenGLRenderingEngine.
I want to take a preventative stance against the diamond problem instead of dealing with it when it becomes a problem, especially since I like to write code that is as easy for someone else to use as possible and I don't want them to have to modify my classes so that they can create particular class heirarchies e.g. if Bob wanted to do this:
class BobsRenderingEngine : public virtual RenderingEngine
{ /* Declares additional pure virtual methods only */ }
class BobsOpenGLRenderingEngine : public SimpleOpenGLRenderingEngine,
public BobsRenderingEngine
{ /* Defines the methods declared in BobsRenderingEngine */ }
This would not be possible if I had not made SimpleOpenGLRenderingEngine extend RenderingEngine virtually. I am aware that the probability of Bob wanting to do this may be very low.
So, I have begun using the convention of always extending pure virtual classes virtually so that multiple inheritance from them does not cause the diamond problem. Maybe this is due to me coming from Java and tending to only use single inheritance with non-pure virtual classes. I'm sure it is probably overkill in some situations but are there any downsides to using this convention? Could this cause any problems with performance/functionality etc.? If not I don't see a reason not to use the convention, even if it may often not be needed in the end.
I would say that, in general, encouraging inheritance is a bad idea (and that's what you are doing by using virtual inheritance). Few things are actually well represented with a tree structure which is implied by inheritance. In addition I find that multiple inheritance tend to break the single responsibility rule. I do not know your exact use case and I agree that at times we have no other choice.
However in C++ we have another way to compose objects, encapsulation. I find that the declaration below is far easier to understand and manipulate:
class SimpleOpenGLRenderingEngine
{
public:
RunnableEngine& RunEngine() { return _runner; }
RenderingEngine& Renderer() { return _renderer; }
operator RunnableEngine&() { return _runner; }
operator RenderingEngine&() { return _renderer; }
private:
RunnableEngine _runner;
RenderingEngine _renderer;
};
It is true that the object will use more memory than with virtual inheritance, but I doubt objects that complex are created in massive numbers.
Now let's say you really want to inherit, for some external constraint. Virtual inheritance is still hard to manipulate: you are probably comfortable with it, but people deriving from your classes may not, and will probably not think too much before deriving. I guess a better choice would be to use private inheritance.
class RunnableEngine : private Engine
{
Engine& GetEngine() { return *this; }
operator Engine&() { return *this; }
};
// Similar implementation for RenderingEngine
class SimpleOpenGLRenderingEngine : public RunnableEngine, public RenderingEngine
{ };
Short answer: Yes. You nailed it.
Long answer:
So, I have begun using the convention of always extending pure virtual classes
Note: the proper term is abstract classes, not "pure virtual classes".
I have begun using the convention of always extending [abstract] classes virtually so that multiple inheritance from them does not cause the diamond problem.
Indeed. This is a sound convention, but not just for abstract classes, for all classes which represents an interface, some of which have virtual functions with default implementations.
(The shortcomings of Java force you to only put pure virtual functions and no data member in "interfaces", C++ is more flexible, for good, as usual.)
Could this cause any problems with performance
Virtual-ness has a cost.
Profile your code.
Could this cause any problems with [] functionality etc.?
Possibly (rarely).
You cannot unvirtualise a base class: if some specific derived class needs to have two distinct base class subobjects, you cannot use inheritance for both branches, you need containment.
Well, it's pretty simple. You violated the the single responsibility principle (SPR) and this is the cause of your problem. Your "Engine" class is a God class. A well-designed hierarchy does not invoke this problem.

is base class list the right place to indicate virtual inheritance?

I have never seen a class used as virtual and nonvirtual base (i.e. if some class is intended to be an ancestor then we usually know in advance about type of inheritance - virtual or nonvirtual).
So I suppose that there is an error-prone freedom in c++ to specialize "virtual" inheritance in base class list. It should be better to specify as "virtual" the base class itself
Or maybe I'm wrong?
If no, can anybody describe some technics to prevent accidental nonvirtual inheritance for such a "virtual" class?
Or there are some perspectives in upcoming c++ standards?
(Sorry if duplicate)
Some examples
1) ReferenceCounted class as base for all classes that some reference-count-based smartpointer can point to. We need to prevent duplicates of this base instances (and reference counters). There are no reasons to use this class as nonvirtual base, except of optimization.
2) A hierarchy of interfaces and corresponding hierarchy of implementations
(interfaces hierarchy must be "virtual" in this case)
// interfaces:
struct BaseIface{
void virtual func()=0;
};
struct DerivedIface: public virtual BaseIface{
void some_another_func()=0;
}
// implementations
class BaseImpl: public virtual BaseIface{
void virtual func(){....};
}
class DerivedImpl: public BaseImpl, public virtual DerivedIface{
void some_another_func(){...};
}
I suspect that in many cases nonvirtual inheritance is not a conceptual need, it used only to reduce virtual inheritance overhead (and sometimes for an ability to static_cast<> to drived :)
Note, that Java used ONLY virtual (in terms of c++) inheritance for interfaces, and I don't know any complains that this language lacks "nonvirtual" (it is esentially less expressive language than c++ but this "feature" is not it's main fault :).
There's not really much way you could do this in the base class (nor would you really want to). It's perfectly reasonable to use a base class for both virtual and non-virtual inheritance.
What you'd really like would be to specify the virtual inheritance in the most derived class, where currently has to be specified in the intermediate classes. Unfortunately, I don't see much way around that -- even though virtual inheritance becomes necessary (primarily) when a class derives from two (or more) other classes that each have a common base, the virtual inheritance really governs how those two other classes are compiled, so if you (only) specified it in the most derived class, you'd end up with something almost like export, where you might need to go back and re-compile those intermediate classes based on the most derived class specifying virtual inheritance (and have some way to store the intermediate classes compiled both ways since it might be used either or both ways).

Abstract Base Class with Data Members

If I'm creating an abstract base class, and the classes derived from it are going to have some of the same data members, is it better practice to make those members private in the abstract base class and give protected access to them? Or to not bother and just put the data members in the derived classes. This is in C++.
The main question to ask in an OOP setting is: Where does this data belong?
In an inheritance relationship, Data (and functionality) should be defined at the highest stage where it is more or less invariant. This promotes maximum modularity and code-reuse. For example, assume two classes:
class Human;
class Student : public Human;
When adding a data member 'm_Arms', we determine the 'Human' level as the best place to define the data, its usage and its visibility to the derived classes, based on the following questions:
Will specializations of humans require more-or-less invariant behavior from the human's arms? i.e. Will they be able to do something that a 'generic' human normally cannot? - (determining common data).
Will the student (or other possible Human specializations) require direct access to it? (determining visibility to child classes).
If visible, which functions are common? (determining associated common functions)
The context should be thought of from the base class's perspective - even if there is one additional is-a-Human class that can do something extra, then it needs to have access to the data. e.g. If for some reason, you decide class Robocop : public Human, you need access to his thigh directly to store the gun inside. Under this architecture, Thigh then needs to become visible to all child classes of Human.
The architecture can be refined using the same principles of data modularity, function modularity and visibility. For example, when defining the class Robocop, The base class Human can be further extracted as follows to allow a change in visibility, and consequent changes in functionality.
class Human;
class NormalHuman : public Human; //declare Thigh private here.
class SuperHuman : public Human; //continue using Thigh as protected.
Further, Arms may themselves be made polymorphic, allowing (excuse the unintended dystopic interpretation) factory-based architectures to modularly assemble different types of Humans using Human parts.
If the data belongs to the derived class, let the derived class do what it wants to contain that data.
By placing that data in the base class (not privately), you force every derived class to have it. The derived classes shouldn't be forced to do anything unless they need to fill out the data member, for example. The base class defines what derived classes must do, not how they should do it.
If you find there might be a common theme, you can make a derived class that has those members and implementations, which is then intended to be the base class for those that want to use it. For example:
struct car
{
virtual ~car(){}
virtual unsigned year(void) const = 0;
virtual const std::string make(void) const = 0;
}
// Dodge cars can feel free to derive from this instead, it's just a helper
struct dodge_car
{
virtual ~car(){}
virtual unsigned year(void) const = 0;
const std::string make(void) const
{
static const std::string result = "Dodge";
return result;
}
}
And so on. But you see, any derived classes still have the choice of implementing the entire car interface. This also improves code cleanliness. By keeping your interface a real interface, implementation details won't get in the way.
Any variables your base class uses should be private, because derived classes don't need to know how it works, in the same way users of your derived class don't need to know how the internals of the derived class work.
How can you make members private and give protected access?
Derived class cannot access base class' private members.
Would Derived class A and Derived class B both need those data members you are talking about? If yes, then put them in base class and make it protected yes.
I know, I actually wanted to post a comment, but I don't know how. May be I need more reputation?
Don't think about what some of your derived classes would do, think about what all of them must do, when writing the base class. In other words, think about the base class itself and the guarantees it makes—its interface.
C++ doesn't have a separate concept of "interface definition" and just reuses classes for that. (Or duck typing in templates.) Because of this, be careful how you write your abstract interface classes so you don't impose restrictions on implementations.
I'm not answering either yes or no because you haven't given enough information, and the answer depends on those other details; but if you follow the guidelines I've briefly laid out, you'll be in decent shape.
There's nothing wrong with having some of the data (and of the implementation, i.e. methods) in the base class.
The base class could be virtual by the mere fact that only one of its methods must be implemented in derived class. The decision of making these variables and methods [of the base class] private, protected or even public, is a case by case issue.
For example the base class could have a public method, a protected method and/or data, and a few private methods.