When I declare a base class, should I declare all the functions in it as virtual, or should I have a set of virtual functions and a set of non-virtual functions which I am sure are not going to be inherited?
A function only needs to be virtual iff a derived class will implement that function in a different way.
For example:
class Base {
public:
void setI (int i) // No need for it to be virtual
{
m_i = i;
}
virtual ~Base () {} // Almost always a good idea
virtual bool isDerived1 () // Is overridden - so make it virtual
{
return false;
}
private:
int m_i;
};
class Derived1 : public Base {
public:
virtual ~Derived () {}
virtual bool isDerived1 () // Is overridden - so make it virtual
{
return true;
}
};
As a result, I would error the side of not having anything virtual unless you know in advance that you intend to override it or until you discover that you require the behaviour. The only exception to this is the destructor, for which its almost always the case that you want it to be virtual in a base class.
You should only make functions you intend and design to be overridden virtual. Making a method virtual is not free in terms of both maintenance and performance (maintenance being the much bigger issue IMHO).
Once a method is virtual it becomes harder to reason about any code which uses this method. Because instead of considering what one method call would do, you must consider what N method calls would do in that scenario. N represents the number of sub classes which override that method.
The one exception to this rule is destructors. They should be virtual in any class which is intended to be derived from. It's the only way to guarantee that the proper destructor is called during deallocation.
The non-virtual interface idiom (C++ Coding Standards item 39) says that a base class should have non-virtual interface methods, allowing the base class to guarantee invariants, and non-public virtual methods for customization of the base class behaviour by derived classes. The non-virtual interface methods call the virtual methods to provide the overridable behaviour.
I tend to make only the things I want to be overridable virtual. If my initial assumptions about what I will want to override turn out to be wrong, I go back and change the base class.
Oh, and obviously always make your destructor virtual if you're working on something that will be inherited from.
If you are creating a base class ( you are sure that somebody derives the class ) then you can do following things:
Make destructor virtual (a must for base class)
Define methods which should be
derived and make them virtual.
Define methods which need not be ( or
should not be) derived as
non-virtual.
If the functions are only for derived
class and not for base class then mark
them as protected.
Compiler wouldn't know which actual piece of code will be run when pointer of base type calls a virtual function. so the actual piece of code that would be run needs to be evaluated at run-time according to which object is pointed by base class pointer. So avoid the use of virtual function if the function is not gonne be overriden in an inherited class.
TLDR version:
"you should have a set of virtual functions and a set of non-virtual functions which you are sure are not going to be inherited." Because virtual functions causes a performance decrease at run-time.
The interface functions should be, in general, virtual. Functions that provide fixed functionality should not.
Why declare something virtual until you are really overriding it? I believe it's not a question of being sure or not. Follow the facts: is it overriden somewhere? No? Then it must not be virtual.
Related
Yes I have seen a lots of posts about using the keywords virtual and override for destructors in C++. I also think I understand the usage:
if a base class has a virtual destructor and a derived class overrides it, if the signatures are different, the program will not compile due to override.
However I am wondering - or I have seen it also several times in someones code, that it is used like this:
class Base
{
public:
~Base();
};
class Derived : public Base
{
public:
~Derived() override;
};
Does this override on a destructor of a non-virtual function in the base class actually has any impact on the program / compiling or anything? Or is it just used wrongly in that case?
You code doesn't compile because Base::~Base is not virtual.
Oh ok, maybe I have overseen this: if the Base class derives from
another class, say SuperBase class - which has a virtual destructor,
then the destructor of Base would be virtual without using the keyword
right?
Correct. If a method is virtual in a base class, then the method in the child class with the same name and same signature will also be implicitly virtual. virtual keyword can be omitted.
A good practice is to always use the keyword override on a method intended to override. This has two big advantages: it makes it clear to a human reader that the method is virtual and overrides and it avoid some bugs where the method is indented to override, but it silently doesn't (e.g. const mismatch).
Destructors are a special case in the sense that that they override a parent virtual destructor, even if they have different names.
So, based on a cursory search, I already know that calling a virtual function (pure or otherwise) from a constructor is a no go. I have restructured my code to ensure that I am not doing that. While this causes the user of my classes to add an extra function call in their code, this is really not that big of a deal. Namely, instead of calling the constructor in a loop, they now call the function which (in fact!) increases performance of the code since we don't have the housekeeping of building and destroying the object in question every time.
However, I have stumbled across something interesting...
In the abstract class I have something like this:
// in AbstractClass.h:
class AbstractClass {
public:
AbstractClass() {}
virtual int Func(); //user can override
protected:
// Func broken up, derived class must define these
virtual int Step1() = 0;
virtual int Step2() = 0;
virtual int Step3() = 0;
// in AbstractClass.cpp:
int AbstractClass::Func() {
Step1();
// Error checking goes here
Step2();
// More error checking...
// etc...
}
Basically, there is a common structure that the pure virtual functions follow most of the time, but if they don't Func() is virtual and allows the derived class to specify the order. However, each step must be implemented in derived classes.
I just wanted to be sure that there's nothing that I necessarily am doing wrong here since the Func() function calls the pure virtual ones. That is, using the base class, if you call StepX(), bad things will happen. However, the class is utilized by creating a derived object and then calling Func() (e.g. MyDerivedObject.Func();) on that derived object, which should have all the pure virtual functions overloaded properly.
Is there anything that I'm missing or doing incorrectly by following this method? Thanks for the help!
Func is calling the virtual ones, not the pure virtual ones. You would have to qualify the calls with a scope operator, i.e. AbstractClass::Step1() to call THAT (virtual pure) function. Since you are not, you will always get an implementation by a derived class.
A virtual function in a base class makes the derived classes able to override it. But it seems things stop there.
But if the base class virtual function is pure, that forces the derived classes to implement the function.
As a side comment you can make the Step1, Step2, Step3 methods private so that you'll be prevented by the compiler from directly calling them.
I'm looking at the following code in my book:
class Shape
{
public:
Shape(){}
~Shape(){}
virtual long getArea() = 0; // Pure virtual function
virtual long getPerim() = 0;
virtual void draw() = 0;
};
Now it says that these virtual functions make the class abstract (which I understand from Java), so the class cannot be instantiated.
However, it says: "a class is in abstract data type by including one or more virtual functions in the class declaration."
Would this mean if I declared a class with ONE pure virtual function:
class Shape
{
public:
Shape(){}
~Shape(){}
virtual long getArea() = 0; // Only pure virtual function
virtual long getPerim(){}
virtual void draw(){}
};
does the whole class become abstract? Because if a class has 100+ methods, it'll be tedious to write =0 for every method if I decide to make it abstract later.
Yes, a single pure virtual method is enough to make the class abstract.
Moreover, you can always make the destructor pure virtual if no other methods are suited to be pure.
Also, your destructor should probably be virtual, since you're obviously going to inherit from this class. This is mandatory if you plan on deleting objects of a derived type through a pointer to a base type.
You are correct in that one pure virtual method is enough to make the class abstract. That means you must implement the method in a derived class to instantiate an instance (of the derived class).
I have issues with your "class with 100+ methods". Usually this is a sign of very poor design.
I also have issues with your "tedious to write =0 for every method" attitude. Firstly I do not see why it is any more tedious to write =0 than it is to write {} as a default no-op implementation (and if the method returns anything, like getPerim() does, you risk undefined behaviour by not returning something). Primarily though, business logic dictates whether or not there is a default behaviour, and not the effort of writing.
Remember the Liskov substitution principle: Although one cannot have an instance of your base class, someone will have a pointer or reference to one, and call virtual methods on it without having to know what class they really have. (Incidentally Liskov was female, first name Barbara, and stated this principle sometime around 1983).
Your abstract base class should almost certainly have a virtual destructor, by the way.
Methods that will not change the state of the class should be declared const.
Marking a function pure doesn't just make the class abstract, it makes any derived class that doesn't override the function also abstract.
So, if you want to force derived classes to implement all those functions, then make them all pure. If it makes sense for a derived class to implement only getArea and not the other two, then only mark getArea pure. In this example I suspect that it doesn't make sense, since if all the derived class has added is a way to compute the area, there's still no way that the base class can compute the perimeter.
Declaring a method as pure virtual means that classes that inherit your class will have to implement that method or leave it pure virtual, in which case the derived class will also be an abstract class that cannot be instantiated.
Also, as Luchian said previously, you should always declare the destructor as virtual for every class that will be inherited.
This has probably been asked before on SO, but I was unable to find a similar question.
Consider the following class hierarchy:
class BritneySpears
{
public:
virtual ~BritneySpears();
};
class Daughter1 : public BritneySpears
{
public:
virtual ~Daughter1(); // Virtual specifier
};
class Daughter2 : public BritneySpears
{
public:
~Daughter2(); // No virtual specifier
};
Is there a difference between Daughter1 and Daughter2 classes ?
What are the consequences of specifying/not specifying virtual on a sub-class destructor/method ?
No you technically do not need to specify virtual. If the base method is virtual then C++ will automatically make the matching override method virtual.
However you should be marking them virtual. The method is virtual after all and it makes your code much clearer and easier to follow by other developers.
You do not need it, but marking it so may make your code clearer.
Note: if your base class has a virtual
destructor, then your destructor is
automatically virtual. You might need
an explicit destructor for other
reasons, but there's no need to
redeclare a destructor simply to make
sure it is virtual. No matter whether
you declare it with the virtual
keyword, declare it without the
virtual keyword, or don't declare it
at all, it's still virtual.
Virtual is automatically picked up on derived method overrides regardless of whether you specify it in the child class.
The main consequence is that without specifying virtual in the child it's harder to see from the child class definition that the method is in fact virtual. For this reason I always specify virtual in both parent and child classes.
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;
};