views:

129

answers:

2

I have a small program to demonstrate simple inheritance. I am defining a Dog class which is derived from Mammal. Both classes share a simple member function called ToString(). How is Dog overriding the implementation in the Mammal class, when i'm not using the virtual keyword? (Do i even need to use the virtual keyword to override member functions?)

mammal.h

#ifndef MAMMAL_H_INCLUDED
#define MAMMAL_H_INCLUDED

#include <string>

class Mammal
{
    public:
        std::string ToString();
};

#endif // MAMMAL_H_INCLUDED

mammal.cpp

#include <string>
#include "mammal.h"

std::string Mammal::ToString()
{
    return "I am a Mammal!";
}

dog.h

#ifndef DOG_H_INCLUDED
#define DOG_H_INCLUDED

#include <string>
#include "mammal.h"

class Dog : public Mammal
{
    public:
        std::string ToString();
};

#endif // DOG_H_INCLUDED

dog.cpp

#include <string>
#include "dog.h"

std::string Dog::ToString()
{
    return "I am a Dog!";
}

main.cpp

#include <iostream>
#include "dog.h"

using namespace std;

int main()
{
    Dog d;
    std::cout << d.ToString() << std::endl;
    return 0;
}

output

I am a Dog!

I'm using MingW on Windows via Code::Blocks.

+5  A: 

It's not overriding the ToString method in the base class as the base class method is not virtual. It is simply hiding that function with a function with an identical signature.

When you call ToString() on a Dog object the Dog::ToString method is called. Why would it call any other ToString() method; the Dog:: declaration is the first one found? virtual dispatch would only happen (and only be needed) when being called through a pointer or reference to a base class object.

If you needed to call the base class method on a Dog object you would have to qualify it explicitly.

d.Mammal::ToString()
Charles Bailey
+7  A: 

Your code uses a Dog object directly, so when you call ToString(), it's statically bound to Dog::ToString(), and produces "I am a Dog!".

To demonstrate polymorphism you can start with a pointer (or reference) to the base class, but set it to refer to an object of the derived class:

Dog d;
Mammal &m = d;

std::cout << m.ToString(); // will produce "I am a Mammal!".
std::cout << d.ToString(); // will produce "I am a Dog!"

Invoked that way, if you make ToString virtual, the output will depend on the type of object pointed at instead of the type of the pointer/reference itself (so both of the invocations above would produce "I am a Dog!").

Jerry Coffin