Wednesday, October 30, 2013

Pure Virtual Functions


What is a pure virtual function?

A pure virtual function is a function that has the notation "= 0" in the declaration of that function. Why we would want a pure virtual function and what a pure virtual function looks like is explored in more detail below.
Here is a simple example of what a pure virtual function in C++ would look like:

Simple Example of a pure virtual function in C++

class SomeClass {
public:
   virtual void pure_virtual() = 0;  // a pure virtual function
   // note that there is no function body  
};

The pure specifier



The "= 0" portion of a pure virtual function is also known as the pure specifier, because it’s what makes a pure virtual function “pure”. Although the pure specifier appended to the end of the virtual function definition may look like the function is being assigned a value of 0, that is not true. The notation "= 0" is just there to indicate that the virtual function is a pure virtual function, and that the function has no body or definition. Also note that we named the function “pure_virtual” – that was just to make the example easier to understand, but it certainly does not mean that all pure virtual functions must have that name since they can have any name they want.

Can a pure virtual function have an implementation?

The quick answer to that question is yes! A pure virtual function can have an implementation in C++ – which is something that even many veteran C++ developers do not know. So, using the SomeClass class from our example above, we can have the following code:
class SomeClass {
public:
   virtual void pure_virtual() = 0;  // a pure virtual function
   // note that there is no function body  
};

/*This is an implementation of the pure_virtual function
    which is declared as a pure virtual function.
    This is perfectly legal:
*/
void SomeClass::pure_virtual() {
    cout<<"This is a test"<<endl;
}

Why would you want a pure virtual function to have an implementation?

It is actually pretty rare to see a pure virtual function with an implementation in real-world code, but having that implementation may be desirable when you think that classes which derive from the base class may need some sort of default behavior for the pure virtual function. So, for example, if we have a class that derives from our SomeClass class above, we can write some code like this – where the derived class actually makes a call to the pure virtual function implementation that is inherited:
//this class derives from SomeClass
class DerivedClass: public SomeClass {

virtual void pure_virtual() {

/*
Makes a call to the pure virtual function 
implementation that is inside the SomeClass
class. This can happen because DerivedClass
may not have anything appropriate to define
for this function, so it just calls the SomeClass's
implementation
*/

SomeClass::pure_virtual();  

}

};
Something else that is definitely worth noting in the code above is the fact that the call to the “SomeClass::pure_virtual();” function is valid because of the fact that the pure_virtual function declaration is public in the SomeClass class. That call would also be valid if the pure_virtual function declaration is protected, because the DerivedClass does derive from the SomeClass class. However, if the pure_virtual function declaration was private in the SomeClass class, then a compiler error would result when the “SomeClass::pure_virtual();” call is made in the DerivedClass class, because it would obviously not have access to that function implementation.

Pure virtual functions can not have a definition inside the function declaration

If you do mistakenly try to give a declaration of a pure virtual function a definition as well, then the compiler will return an error when it comes across that code. Note that there is however an exception to this in Microsoft’s Visual C++ implementation, which specifically allows this. This is also known as an inline definition, which is completely different from the use of the inline keyword – which you can read about here Inline vs macro. So, suppose we have the following code:
class SomeClass {
public:
  /*note that we added braces that are normally
     associated with a function body and definition:
  */
   virtual void pure_virtual() = 0 { }; //ERROR (except in MS VC++)
};
The code above is considered ill formed by the C++ 03 standard in Clause 10.4, paragraph 2, which says that “a function declaration cannot provide both a pure-specifier and a definition”.
Running the code above will actually result in a compiler error, because a pure virtual function can not have a definition within the declaration of the pure virtual function.

A class with a pure virtual function is called an abstract class

Any class that has at least one pure virtual function is called an abstract class. This means that in our example above, the SomeClass class is an abstract class. An abstract class cannot have an instance of itself created. So, using our example class from above, the following code would not work:
SomeClass aClass;  //Error!  SomeClass is abstract
This also means that any class that derives from an abstract class must override the definition of the pure virtual function in the base class, and if it doesn’t then the derived class becomes an abstract class as well.

Pure virtual functions in Java

In Java, pure virtual methods are declared using the abstract keyword – note that C++ does not use the keyword “abstract” as part of the language itself, although C++ does have abstract classes – any class with at least one virtual function is considered to be abstract. So, in Java abstract methods are the equivalent of pure virtual functions in C++. In Java, an abstract method cannot have a body, just like a pure virtual function in C++. A class containing abstract methods must itself be declared abstract. But, an abstract class is not necessarilly required to have any abstract methods. An abstract class cannot be instantiated.

When should pure virtual functions be used in C++?

In C++, a regular, "non-pure" virtual function provides a definition, which means that the class in which that virtual function is defined does not need to be declared abstract. You would want to create a pure virtual function when it doesn’t make sense to provide a definition for a virtual function in the base class itself, within the context of inheritance.

An example of when pure virtual functions are necessary

For example, let’s say that you have a base class called Figure. The Figure class has a function called draw. And, other classes like Circle and Square derive from the Figure class. In the Figure class, it doesn’t make sense to actually provide a definition for the draw function, because of the simple and obvious fact that a “Figure” has no specific shape. It is simply meant to act as a base class. Of course, in the Circle and Square classes it would be obvious what should happen in the draw function – they should just draw out either a Circle or Square (respectively) on the page. But, in the Figure class it makes no sense to provide a definition for the draw function. And this is exactly when a pure virtual function should be used – the draw function in the Figure class should be a pure virtual function.

No comments:

Post a Comment