A class that contains pure virtual functions is called
abstract or
interface class and concrete class derived from
abstract class is called
implementation class. Since
abstract class just defines the interface i.e. what data a class contain and what operations can be performed on it. Virtual functions in abstract class are usually declared but not defined. It is the responsibility of derived class to define it.
Declaration of pure virtual function in C++:
virtual <return type> <user defined function name>(<arguments>) = 0;
e.g.
virtual void Speak(int a) = 0;
But compiler does not complain even if you give the definition of pure virtual function and in some cases it is useful. Let us try to understand where it can be helpful and when that function get called as there can not be object of
abstract class.
Let us say we have base class
Aeroplane and
AeroplaneA and
AeroplaneB are derived from it. class
Aeroplane has a method called
fly() that defines general way of flying. Let us say
AeroplaneA and
AeroplaneB have their own way of flying because they are special sort of planes (Jet or something :P). How can we design it in C++?
First approach: Make function fly() pure virtual and define the fly() function in every class which is an intuitive solution.
But let us say for another 3
Aeroplanes C, D and
E have same general of flying(They are not special kind of planes). In that case you will have to copy the code of
fly() function of
Aeroplane class to the
fly() function of class
AeroplaneC,
AeroplaneD and
AeroplaneE that is duplicate code and moreover let us say there is some bug in flying functionality you will have to change 3 functions and you may forget to modify one or two of them. Hence It is really difficult to maintain.
class Aeroplane {
// constructor,destrcutor etc
public :
virtual void fly() = 0;
} ;
class AeroplaneA : public Aeroplane{
// constructor,destrcutor etc
public :
virtual void fly() {
//own functionality
}
} ;
class AeroplaneB : public Aeroplane{
// constructor,destrcutor etc
public :
virtual void fly() {
//own functionality
}
} ;
class AeroplaneC : public Aeroplane{
// constructor,destrcutor etc
public :
virtual void fly() {
// general fly functionality Duplicate code
}
} ;
class AeroplaneD : public Aeroplane{
// constructor,destrcutor etc
public :
virtual void fly() {
// general fly functioanlity.. Duplicate code
}
} ;
//similarly for AeroplaneE
Second Approach : Make function fly() virtual instead of pure virtual. Put the general flying functionality in fly() function of Aeroplane class and whichever class wants to override this functionality it can do.
Now we don't need to declare fly() function in AeroplaneC,AeroplaneD and AeroplaneE. Hence for objects of type AeroplaneA or AeroplaneB their own version of fly() will be called. and for rest of the Aeroplanes general fly() function in Aeroplane class will be called.
class Aeroplane {
// constructor,destrcutor etc
public :
virtual void fly() {
// general fly functionality
}
} ;
class AeroplaneA : public Aeroplane{
// constructor,destrcutor etc
public :
virtual void fly() {
//own functionality
}
} ;
class AeroplaneB : public Aeroplane{
// constructor,destrcutor etc
public :
virtual void fly() {
//own functionality
}
} ;
class AeroplaneC : public Aeroplane{
// constructor,destrcutor etc
// don't need to define fly function here
} ;
class AeroplaneD : public Aeroplane{
// constructor,destrcutor etc
// don't need to define fly function here
} ;
It looks perfect. Isn't it?
But unfortunately answer is No. It can also cause some problems. e.g.
Let us say another AeroplaneF(special plane) which has its own way of flying is introduced and designer forget to over ride the fly() function, compiler will not complain, your code will just start working without even a warning. It will be caught as part of bug etc. But what if it is not even caught in testing? For crucial and such critical design you can not take risk or you should not do such mistakes. During the actual run, your Aeroplane may just crash. :(
So what do we do? Neither solution looks like a good solution. Both are bug prone.
Don't worry we will not let your plane crash.. :) C++ compiler gives you a very nice solution for such problems.
Solution : Define pure virtual function. By defining pure virtual function, we can put general fly() functionality in fly() function of Aeroplane and since fly() function is pure virtual all concrete class needs to redefine it and there we can simply call fly() function of class Aeroplane. Hence we have taken care of both problems. Now there is no duplicate code and compiler enforces you to define virtual function in each concrete class.
class Aeroplane {
// constructor,destrcutor etc
public :
virtual void fly() = 0 {
// general fly functionality
}
} ;
class AeroplaneA : public Aeroplane{
// constructor,destrcutor etc
public :
virtual void fly() {
//own functionality
}
} ;
class AeroplaneB : public Aeroplane{
// constructor,destrcutor etc
public :
virtual void fly() {
//own functionality
}
} ;
class AeroplaneC : public Aeroplane{
// constructor,destrcutor etc
virtual void fly() {
Aeroplane::fly();
}
} ;
class AeroplaneD : public Aeroplane{
// constructor,destrcutor etc
virtual void fly() {
Aeroplane::fly();
}
} ;
Reference : One of the Item from 50 specific ways to improve your C++ skills by Scott Meyer.