Overriding or Overloading in C++?

Occasionally I’ve heard these terms used interchangeably – but they actually refer to two completely separate concepts.

So what’s what?

Overloading describes the creation of a method with the same name as an existing method, but different parameters. For example:

int method();
int method(int);
int method(int, double);

Overriding describes the creation of a method in a derived class  with the same name and parameters as an existing method in its base class.

class base {
public:
    int method();
};

class derived : public base
{
public:
    int method();
};

The actual method that is called in this case depends on what kind of object you are dealing with, and whether the base class is abstract, the methods are virtual, and so on.

How do you remember the difference?

Think of it as load versus ride.

Overloading gives you loads of methods in the same class with different parameters.

Overriding lets you ride on the back of a method declared in a base class.

Easy, eh?

Initialization Lists in C++

When you first start using C++ you tend to set member variables with default values inside your constructor.

For example, you might have a class called Message that has three variables, and your constructor sets the default values like this:

Message::Message()
{
    messageLength = 0;
    messageType = 0;
    messageBody = "Empty message";
}

This is acceptable and I’ve seen it in hundreds of classes, but there is a better way.

When setting member variables to their defaults, it can be more efficient to set them in an initialization list. You create this by adding a colon after the constructor name and listing the variables underneath separated by a comma. You set the default value by adding it in brackets, e.g.

Message::Message() :
    messageLength(0),
    messageType(0),
    messageBody("Empty message")
{
}

In my opinion this also aids readability, since you are leaving the body of the constructor free to do ‘real’ construction work (if necessary), and you don’t have to hunt through lines of code to determine if and where a variable was set to a default value*.

Why is it more efficient?

Setting defaults in the body of the constructor uses assignment, whereas in the initialization list it uses initialization (you could have guessed from the name, right?).

If you are initializing classes (rather than built-in types, in which case this doesn’t apply), then using assignment means that behind the scenes you call the default constructor, followed by an assignment to set the variable. Putting the string variable in the initialization list means that you only call the copy constructor to set up the variable – so it costs one method call, not two.

The order matters

If you don’t enter the member variables in the initialization list in the same order as they appear in the header file (declaration), then gcc will prompt you with a warning:

warning: 'Message::MessageBody' will be initialized after
warning: 'int Message::MessageLength'
warning: when initialized here

Should you care about this warning?

I would argue that you should care about all warnings! It appears because it is possible that a member variable may rely on another member variable during initialization. For example, say your header contains the following:

int total;
int multiplier;

And you initialize them like this:

Constructor::Constructor() :
    multiplier(3),
    total(multiplier * SOME_OTHER_VALUE)
{
}

This won’t work – total will be initialized first (no matter where you put it in your initialization list), because it is declared first in the header, so what will the value of multiplier be at this point? That depends on your compiler, but it almost certainly won’t be what you were expecting!

*Note that you can’t initialize the members of an array in a list – this must be done in the body of the constructor.

What is Encapsulation?

This is the final post in the series of the three cornerstones of object oriented programming. Next week I’m going back to a nice low-level subject – the bitwise operators :-).

So. What is encapsulation?

I previously defined this as the ability of objects* to maintain their internal workings independently from the program they are used in.

This is actually the simplest of the three concepts we’ve covered. With respect to C++, encapsulation describes the use of a class to contain both its relevant data, and the methods to manipulate its own data.

In practice

As a simple example, you might define a class called Message. This class can contain various data members, such as the sender’s address, the date the message was written, the destination address, and of course, the actual message inside.

The class can also contain methods to manipulate a Message object. For example it might have a method to set the object status to ‘read’, and another method to print the message to the screen.

The fact that the Message class both contains its own data, and provides a way to interact with that data, is what encapsulation is all about.

It’s such a fundamental part of C++ (and other OO languages), that it is often taken for granted.

Why is this a good thing?

The benefits of encapsulation are:

  • It can restrict access to an object’s data.

If data is declared as private and methods are generated to access that data, it can provide a good level of control over the data and how it is used.

  • It allows the programmer to modify the object under-the-hood without disrupting the rest of the program.

If you want to change the internals of your class, you can do so without having to modify code elsewhere in the program, as long as you keep the methods to access that class the same.

Encapsulation is the class not the object

Note that encapsulation is provided by the class, not the instantiated object (there is a subtle difference). This is because a class can provide the ability to access information about every object that is instantiated from it, whereas a single object is just that.

And that wraps up our mini-guide to OOP. Hope it was useful, and don’t forget to pop back soon for some fun with bitwise operators.

 

*In C++ note that is it officially the class that is the unit of encapsulation, not the individual object itself. 

What is Inheritance?

Today we’ll take a look at inheritance* – the second cornerstone of object oriented programming, as explained in my 5 minute guide to OOP.

In that post, I described inheritance as the ability of objects to derive behaviour patterns from other objects. But what does this mean in practice?

An object can inherit behaviour (in the form of methods), and even data variables, from a parent class, in much the same way as children inherit characteristics from their parents.

Why is this something that we might want to do in programming?

Inheritance accurately models relationships

Using inheritance can make a program easier to understand. The concept that an object derives from another object is quite intuitive. As long as you are deriving correctly, inheritance can help break a complex model down into workable objects. You are deriving correctly when your inherited object IS A base class object. E.g. a glider IS A plane; a dog IS A mammal. If you can’t say this, you should be questioning if inheritance is the correct approach.

Inheritance allows us to create polymorphic objects

By declaring methods as virtual, you have the option of overriding them in derived classes. This is how polymorphism is achieved, as discussed here.

Inheritance allows us to create interfaces

By declaring methods as pure virtual, you can create an abstract base class (ABC) that cannot be instantiated (i.e. it can’t exist as an object in its own right). Consequently you end up with a class that defines a set of methods, but has no implementation of those methods – i.e. a lovely interface.

Inheritance isn’t a solution for reducing/reusing code

Inheritance can reduce the amount of code that needs to be written, but this isn’t why it exists. It’s important to remember this. If you find you are using inheritance to promote code-reuse, then you need to look carefully at whether the relationship between derived class and parent class is still correct.

Multiple inheritance

Multiple inheritance is the process of deriving a class from two or more base classes.

Eek! Why would anyone want to do that? Well, sometimes you need the functionality of two classes combined into one – for example, you may be working with a library and find that a class you have already derived from your own base class also needs to derive from one of the base classes provided in the library. Essentially, if you stick to deriving from abstract base classes, multiple inheritance shouldn’t cause you too much pain.

I’ve worked in places that support opposite ends of the opinion spectrum on this topic. One company unanimously insisted that multiple inheritance was the work of the devil. Another company, several years later, used multiple inheritance like it was going out of fashion.

Having seen its usefulness in live code, but also having been subjected to endless warnings of its dangers, I tend to take a more moderate view. Yes, there is a place for multiple inheritance, but you should be clear about why you need it.

There is no concrete way of deciding if multiple inheritance is the right solution to a particular problem, but if it seems like a simple and elegant way to solve an otherwise tricky issue, then it might just be the right thing to use.

Next week we’ll take a look at the third and final cornerstone of OOP – encapsulation.

*This post discusses public inheritance, not private or protected.