In C++, a pure virtual function is a function declaration that has no implementation in the class where it is declared, but is rather left to the child classes to override and define the function. This means that the parent class cannot be instantiated. In Java this is known as an abstract class or interface.
We use virtual functions whenever we create a class which we expect to be used as a base class. Virtual functions are simply functions that we expect to be overridden by those classes. Whenever we implicitly invoke a virtual method, the most-derived override of that method is automatically invoked, even if we do not know the specific type of that derivative.
Let us consider the following minimal example in C++ which requires some means of differentiating between different types of the same class. For this we will use a type field:
#include
#include
enum g_type {a, b, c};
class bad {
g_type m_type;
public:
bad (g_type type): m_type (type) {}
std::string type() const;
};
std::string bad::type () const {
switch (m_type)
{
case a: return "A";
case b: return "B";
case c: return "C";
}
}
void print_type (const bad& object) { std::cout << object.type() << std::endl;
}
int main () {
bad x (a);
bad y (b);
bad z (c);
print_type (x);
print_type (y);
print_type (z);
}
Output:
A
B
C
This class isn't particularly useful but it is capable of determining it's own type from the type field, which is the only part the really interests us. Other methods that depend upon that type field can obviously make use of a similar switch/case structure to the one found in the bad::type() method, and thus provide implementations that are specific to each of those types. However, this is bad design for several reasons:
All these problems can be address through virtual functions. Consider the following alternative:
#include
#include
class good {
public:
virtual std::string type() const {return "base class";}
};
class a : public good {
public:
virtual std::string type () const override {return "A";}
};
class b : public good {
public:
virtual std::string type () const override {return "B";}
};
class c : public good {
public:
virtual std::string type () const override {return "C";}
};
void print_type (const good& object) {
std::cout << object.type() << std::endl;
}
int main () {
a x;
b y;
c z;
print_type (x);
print_type (y);
print_type (z);
}
Output:
A
B
C
[It should be noted that C++ methods are non-virtual by default while Java methods are virtual by default. While it could be argued that it makes more sense for all methods to be virtual by default, C++ inherits from C and since there are no virtual methods in C, they are non-virtual by default in order to maintain compatibility with C.]
Obviously this example has more classes, but that is entirely the point. Each class (a, b and c) "knows" its own type, so the base class doesn't have to specifically cater for them. The classes a, b and c are simply more specialised versions of their base class, and each caters only for its own type. You will note that although the print_type function expects a "good" object and invokes its type() function, the output is not "base class" as you might expect. Derived objects behave according to their most-derived type, so when you invoke a virtual method, the most-derived override is invoked automatically. This is known as polymorphism, where derived object's behave according to their actual type. This works even when the function knows nothing about the derivatives. However, it only works when we pass objects by reference (or by pointer). If we pass a derived object and the function expects a base class by value rather than by reference, the base class will be copied without the derived portion of the object. This is known as "object slicing" and is usually undesirable.
The implementation greatly reduces the cost of maintenance because if we need a new type we simply derive a new class and that new class caters specifically for that new type and nothing else. We do not have to modify the base class, nor do we have to modify any other classes, we simply override the virtual methods provided by the base class. End-users can also create their own types much more easily, even if they have no access to the source code. All they need to know can be found in the declaration of the "good" base class (which can be found in the class header which must be distributed with the class library). Classes a, b and c can actually be defined in completely separate files (or libraries) in order to maintain modularity.
Moreover, our programs no longer need to include code that will never be invoked, only the classes we physically instantiate need to be compiled, even if we include classes we never actually use. All the code that pertains to a specific class is encapsulated by that class. The "good" class essentially provides the interface to all its derivatives, even if the code that operates upon "good" classes doesn't know anything about those derivatives. And that's just as it should be because when you ship a base class you have no way of knowing what derivatives other programmers may derive from your base class.
Note that all base classes must have a virtual destructor. This is how you determine if a class can be used as a base class or not. If it does not have a virtual destructor and does not inherit from any other classes then it is not intended to be used as a base class. However, if it has one or more virtual methods, it must also have a virtual destructor.
The reason we need a virtual destructor is because derived objects must be destroyed in the reverse order they were constructed. Construction always begins from the least-derived class because a derived object cannot exist until its base class has been fully constructed. But during destruction, the derived class must be destroyed before its base class can be destroyed. If it weren't (if the destructor were not virtual), code that isn't aware of the derived class may destroy the base class, leaving an incomplete object in memory. We can see this working in the following minimal example:
#include
class base {
public:
base () {std::cout<<"creating base"< ~base () {std::cout<<"destroying base"< }; class derived : public base { public: derived () {std::cout<<"creating derived"< ~derived () {std::cout<<"destroying derived"< }; int main () { base* object = new derived; delete object; object = nullptr; } Output: creating base creating derived destroying base As you can see, we constructed a derived object but we didn't destroy it. It's still in memory, but it's no longer valid because its base class no longer exists. Note that the "object" variable is a pointer to the base class of the derived class. This is valid because a derived class is said to be a "kind of" base and is really no different to our print_type function in the previous example which accepted a reference to a "good" object, even though we actually passed references to a, b and c objects. To fix this, we need a virtual destructor: class base { public: base () {std::cout<<"creating base"< virtual ~base () {std::cout<<"destroying base"< }; Now we get the expected behaviour and the objects are both created and destroyed in the correct order: creating base creating derived destroying derived destroying base
You declare a pure virtual function whenever you wish your class to be an abstract data type and require all derivatives of the class to provide an implementation for the pure virtual function. Unlike a non-pure virtual function which needn't be overridden by derivatives, pure virtual functions must be overridden. Once a derivative provides an implementation, that function becomes non-pure virtual, and can then be inherited by derivatives of that derivative.
You declare a pure-virtual method in base classes that are intended to provide a common interface to two or more derived classes. Any class that declares a method as pure-virtual becomes an abstract base class (ABC), also known as an abstract data type (ADT).
You cannot instantiate abstract classes, but that's fine because the intent is to derive classes from the abstract class and define specialised implementations for the pure-virtual methods in each of the derived classes. The base class exists purely to provide a common interface to all its derivatives.
Virtual functions must be implemented in the base class, but they need not be implemented in their derived classes. Derived classes will automatically inherit the base class implementations of all virtual functions, but can override those functions by providing their own implementations. The base class methods can still be called explicitly to provide common functionality. A function that is declared virtual is expected to be implemented by derived classes, but it is not a requirement.
Pure-virtual functions need not be implemented in the base class, but they must be implemented in the derived classes. Any class that declares a pure-virtual function is automatically rendered an ADT (abstract data type) and cannot be instantiated other than through derivation. Derived classes do not inherit any of the abstract base class implementations, but they can call them explicitly. Derived classes that do not implement all the pure-virtual functions inherited from their abstract base classes are automatically rendered abstract themselves, however any implementations they do provide are subsequently treated as virtual methods (and are therefore inherited by derivatives). A concrete class is a class that inherits or implements the sum total of all pure-virtual methods inherited from all abstract base classes. Only concrete classes can be instantiated without being derived from.
[Edit: original answer was incomplete and misleading.]
All virtual functions (including pure-virtual functions) are represented in italics. All non-virtual functions are represented normally. There is no differentiation between pure and non-pure virtual functions, however some people append "=0" to distinguish the pure-virtual functions.
Virtual Functions and Pure Virtual Functions are relevant in the context of class inheritance.Unlike Virtual Functions, Pure Virtual Functions do not require a body. This implies that when a base class defining such a function is inherited, the derived class must implement that function. Furthermore, the base class becomes abstract; meaning you cannot create an instance of the base class even if a body is implemented for the function. You are expected to derive from abstract classes; only the derived classes that implement all the inherited Pure Virtual functions can be instantiated.Here are some examples of Virtual and Pure Virtual function signatures:- Virtual Function: E.g. virtual void myFunction();- Pure Virtual Function: E.g. virtual void myFunction() = 0;
No, inlining is done at compile time whereas virtual functions are resolved at run time(late binding). So, virtual functions can't be inlined. Both properties are orthogonal.Inlining is a mere suggestion the compiler may ignore it if it is declared with virtual function.
We make a virtual function pure whenever we wish to make our class an abstract base class (an abstract data type). Unlike a virtual function, pure virtual functions must be overridden by a derived class or by one of its derivatives (the function remains pure virtual until it is overridden, at which point it becomes virtual). Derived classes that do not provide a complete implementation for all the pure virtual functions it inherits become abstract themselves. You cannot instantiate an abstract base class other than through derivation.
A pure-virtual function is a function that must be overridden in derived classes. You simply add "=0" to the end of the function declaration. class AbstractClass { public: virtual void DoSomething()=0; // Pure-virtual. };
All virtual functions (including pure-virtual functions) are represented in italics. All non-virtual functions are represented normally. There is no differentiation between pure and non-pure virtual functions, however some people append "=0" to distinguish the pure-virtual functions.
Virtual functions is a function that can be overridden in inheriting class with the same signature (function name, parameters number, parameters types and return type);Pure virtual function is function that does not have implementation and if class has pure virtual function is called abstract. It is not possible to instantiate that class. Some other class must inherit it and define the body for it (implement). In other words class only have function prototype/declaration(signature) and no definition(implementation).
Virtual Functions and Pure Virtual Functions are relevant in the context of class inheritance.Unlike Virtual Functions, Pure Virtual Functions do not require a body. This implies that when a base class defining such a function is inherited, the derived class must implement that function. Furthermore, the base class becomes abstract; meaning you cannot create an instance of the base class even if a body is implemented for the function. You are expected to derive from abstract classes; only the derived classes that implement all the inherited Pure Virtual functions can be instantiated.Here are some examples of Virtual and Pure Virtual function signatures:- Virtual Function: E.g. virtual void myFunction();- Pure Virtual Function: E.g. virtual void myFunction() = 0;
No, inlining is done at compile time whereas virtual functions are resolved at run time(late binding). So, virtual functions can't be inlined. Both properties are orthogonal.Inlining is a mere suggestion the compiler may ignore it if it is declared with virtual function.
We make a virtual function pure whenever we wish to make our class an abstract base class (an abstract data type). Unlike a virtual function, pure virtual functions must be overridden by a derived class or by one of its derivatives (the function remains pure virtual until it is overridden, at which point it becomes virtual). Derived classes that do not provide a complete implementation for all the pure virtual functions it inherits become abstract themselves. You cannot instantiate an abstract base class other than through derivation.
A pure-virtual function is a function that must be overridden in derived classes. You simply add "=0" to the end of the function declaration. class AbstractClass { public: virtual void DoSomething()=0; // Pure-virtual. };
Dynamic binding is achieved via virtual functions and the virtual table that is associated with every class that declares or inherits a virtual function. The virtual table (or v-table) maps every virtual function (including pure-virtual functions) to a function pointer that points to the most-derived overload. This makes it possible to invoke specific behaviour even when the runtime type of the object is unknown to the caller.
Functions in C++ are separate procedures or subroutines within a program, that can be called as often as required and which can return values back to their callers. That is, when you make a function call, execution passes to the function and then returns to the caller. Functions that are class members are also known as member functions, member methods, or simply methods. These work exactly the same as external functions except they are scoped to the class and have access to private members of the class.
Only class instance methods can be rendered as pure-virtual functions (or pure-virtual methods, to be precise). Non-member functions and static member methods cannot be declared pure-virtual.The implication of declaring a pure-virtual function is that the class to which it is a member becomes an abstract data type (or abstract base class). This means you cannot instantiate an object of that class, you can only derive classes from it. Moreover, the derived classes must also implement the pure-virtual functions or they, too, become abstract data types. Only concrete classes that contain a complete implementation can be instantiated, although they can inherit implementations from their base classes (but not from the class that initially declared the method).Pure-virtual functions ensure that you do not instantiate base class objects that are not intended to be instantiated (they are conceptual rather than actual objects) and that derived objects provide a specific implementation. Typically, all methods of an abstract base class will be declared pure-virtual to ensure correct behaviour in derived classes through a common interface. Abstract base classes will also have few member variables, preferably none at all.For example, a shape is a conceptual object whereas a rectangle, triangle or circle are actual objects. As such they can all be derived from shape. The shape base class need only declare the interface that is common to all shapes, such as Draw(), Rotate(), Mirror() and so on. But since a shape doesn't have enough information to implement these methods, they must be declared pure-virtual. This ensures that shape cannot be instantiated (since it would be meaningless) and that every object derived from shape not only has a common interface, but that each type of shape provides its own specific implementation of those methods. This is not unlike overriding standard virtual functions, however the difference is that you must override the pure-virtual methods; it is not optional unless the derived class is intended to become abstract itself.
There are no pure virtual functions, but there are pure virtual function calls.In C++, classes can define abstract functions. Those are virtual functions for which no implementation is supplied in the class that defines it. Abstract functions are typically used to define a contract. For example, a base class for any vehicle might guarantee that a move() method exists, but only classes derived from vehicle implement this method according to the properties of the specific vehicle: a bike, a car, a skateboard, etc. Classes containing abstract functions are sometimes called abstract classes.The C++ compiler does not allow the creation of an object of type vehicle in this example, because the vehicle class contains an abstract function.Classes derived from vehicle (derived in first or higher degree) must supply an implementation of this method before the compiler allows the creation of an object of this type.Therefore, any valid object descended from vehicle must have an implementation of the move method. However, since it is possible to create pointers to abstract classes (classes that contain abstract functions which have not yet been given an implementation), pure virtual function calls can occur at runtime.Consider this example:class vehicle {public:virtual void move(void) = 0; // abstract function};class motorizedVehicle : vehicle {...};class car : motorizedVehicle {public:virtual void move(void) {... // implementation}};An application cannot create objects of type vehicle or motorizedVehicle, but it can create pointers to those. Those might give access to classes that have no implementation for the move method, and calling it results in a run-time diagnostic known as a pure virtual function call.
A virtual function table is a table of pointers to functions.
Virtual functions are dynamically bound at runtime.