Inheritance helps to reduce the amount of code written or repeated by using a base-derived relation in object-oriented-world. Common functions are collected in a base class and the derived class extends or directly uses the existing base class functions. In some situations base class also can be pointing to different derived classes depending on the run-time behavior.
When base class is used to point to derived class, base class pointer calls overridden base-class methods, if there are any base class virtual method re-implementations in the derived class.
Virtual functions in C++ help to transfer a specific behavior in the base class to derived class by declaring the function
virtual in the base class. Derived is free to re-implement base class virtual functions.
If the derived class does not provide any implementation for the base class virtual functions then the base class virtual functions are called. This is not always the expected behavior because base class virtual functions are declared to be overridden in the derived class.
Following sample project created by qt creator and contains following files:
1- VirtualFunctions.pro
2- main.cpp
3- abstractservice.h
4- abstractservice.cpp
5- activityservice.h
6- activityservice.cpp
7- userservice.h
8- userservice.cpp
VirtualFunctions.pro file contains project configuration.
TARGET = VirtualFunctions
CONFIG += console
TEMPLATE = app
SOURCES += main.cpp \
abstractservice.cpp \
userservice.cpp \
activityservice.cpp
HEADERS += \
abstractservice.h \
userservice.h \
activityservice.h
abstractservice.h is the base class that contains virtual functions.
#ifndef ABSTRACTSERVICE_H
#define ABSTRACTSERVICE_H
#include <stdio.h>
class AbstractService
{
public:
AbstractService();
virtual ~AbstractService();
// calls both base and derived dest
// prevents memory leaks
virtual void insertRecord();
virtual void selectRecord();
virtual void deleteRecord();
virtual void updateRecord();
};
#endif // ABSTRACTSERVICE_H
In the base class abstractservice.h destructor is also defined virtual otherwise derived class destructor is not called at object deletion.
abstractservice.cpp is the base class implementation file that contains implementations for virtual functions, constructor and destructor.
#include "abstractservice.h"
AbstractService::AbstractService()
{
printf("AbstractService::AbstractService called\n");
}
AbstractService::~AbstractService()
{
printf("AbstractService::~AbstractService called\n");
}
void AbstractService::insertRecord()
{
printf("AbstractService::insertRecord called\n");
}
void AbstractService::selectRecord()
{
printf("AbstractService::selectRecord called\n");
}
void AbstractService::deleteRecord()
{
printf("AbstractService::deleteRecord called\n");
}
void AbstractService::updateRecord()
{
printf("AbstractService::updateRecord called\n");
}
userservice.h is the first derived class that contains its own implementations for the virtual functions that are declared in the base class abstractservice.
#ifndef USERSERVICE_H
#define USERSERVICE_H
#include "abstractservice.h"
class UserService : public AbstractService
{
public:
UserService();
~UserService();
void insertRecord();
void selectRecord();
void deleteRecord();
void updateRecord();
};
#endif // USERSERVICE_H
userservice.cpp contains implementation details for the base class virtual functions.
#include "userservice.h"
UserService::UserService()
{
printf("UserService::UserService called\n");
}
UserService::~UserService()
{
printf("UserService::~UserService called\n");
}
void UserService::insertRecord()
{
printf("UserService::insertRecord called\n");
}
void UserService::selectRecord()
{
printf("UserService::selectRecord called\n");
}
void UserService::deleteRecord()
{
printf("UserService::deleteRecord called\n");
}
void UserService::updateRecord()
{
printf("UserService::updateRecord called\n");
}
activityservice.h is the second derived class that re-declares base class virtual functions in its header.
#ifndef ACTIVITYSERVICE_H
#define ACTIVITYSERVICE_H
#include "abstractservice.h"
class ActivityService : public AbstractService
{
public:
ActivityService();
~ActivityService();
void insertRecord();
void selectRecord();
void deleteRecord();
void updateRecord();
};
#endif // ACTIVITYSERVICE_H
activityservice.cpp file contains implementation details for the base class virtual functions.
#include "activityservice.h"
ActivityService::ActivityService()
{
printf("ActivityService::ActivityService called\n");
}
ActivityService::~ActivityService()
{
printf("ActivityService::~ActivityService called\n");
}
void ActivityService::insertRecord()
{
printf("ActivityService::insertRecord called\n");
}
void ActivityService::selectRecord()
{
printf("ActivityService::selectRecord called\n");
}
void ActivityService::deleteRecord()
{
printf("ActivityService::deleteRecord called\n");
}
void ActivityService::updateRecord()
{
printf("ActivityService::updateRecord called\n");
}
Both of the derived classes provide their own implementations for the virtual functions declared in the base class abstractservice.
main.cpp file contains a main function that is creating different base class pointers which are pointing to derived class objects.
#include "userservice.h"
#include "activityservice.h"
int main(int argc, char *argv[])
{
UserService *userServicePtr = new UserService;
userServicePtr->insertRecord();
userServicePtr->selectRecord();
userServicePtr->updateRecord();
userServicePtr->deleteRecord();
delete userServicePtr;
printf("\n");
AbstractService *abstractServiceObjPtr = new AbstractService;
abstractServiceObjPtr->insertRecord();
abstractServiceObjPtr->selectRecord();
abstractServiceObjPtr->updateRecord();
abstractServiceObjPtr->deleteRecord();
delete abstractServiceObjPtr;
printf("\n");
// base class pointer to derived class object
char option = 'a';
AbstractService *serviceObjPtr;
if( option == 'u' )
{
serviceObjPtr = new UserService;
serviceObjPtr->insertRecord();
serviceObjPtr->selectRecord();
serviceObjPtr->updateRecord();
serviceObjPtr->deleteRecord();
delete serviceObjPtr;
printf("\n");
}
else if( option == 'a' )
{
serviceObjPtr = new ActivityService;
serviceObjPtr->insertRecord();
serviceObjPtr->selectRecord();
serviceObjPtr->updateRecord();
serviceObjPtr->deleteRecord();
delete serviceObjPtr;
printf("\n");
}
return 0;
}
At runtime base class pointer serviceObjPtr points to either UserService instance or ActivityService instance.
Console output also shows the order for object creation and destruction.