A question about inheritance and polymorphism

OK, I wrote a program and it was something like this:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
#include <iostream>

// Abstract Parent Class
class Parent
{
  public:
    virtual void DoSomething() = 0;
};

// Derived Class A
class FirstSon: public Parent
{
  public:
    void DoSomething() {
      std::cout << "A" << std::endl;
    }
};

// Derived Class B
class SecondSon: public FirstSon
{
  public:
    void DoSomething() {
      std::cout << "B" << std::endl;
    }
};

// Derived Class C
class ThirdSon: public SecondSon
{
  public:
    void DoSomething() {
      std::cout << "C" << std::endl;
    }
};


In few words, I have a super class from which I'm deriving a class A, from which I'm deriving a class B, from which I'm deriving a class C. The super class has a pure virtual member function, which I want to overload. However, I'm a little confused of what is actually happening. There is nothing wrong with my program, because the correct version of the method DoSomething() is invoked depending on the class that called it.

But my question is: Which version of DoSomething am I overloading? For example, if I call ThirdSon::DoSomething(), is it the overloaded version of SecondSon::DoSomething(), or Parent::DoSomething()? Does this counts as polymorphism?

I did a little test to try to understand, and it was like this:
1
2
3
4
5
6
7
8
9
10
11
int main()
{
  SecondSon s;
  ThirdSon  t;
  Parent*   a;
  Parent*   b;
  a = &s;
  b = &t;
  a -> DoSomething();
  b -> DoSomething();
}


The output was:
B
C


What I actually want to do is to overload in all derived classes the virtual member function from Parent, but I don't know if I did it correctly.
Can someone please explain this to me?
There is no function Overloading in this code. What you are doing is called Overriding. FirstSon::DoSomething implements Parent::DoSomething, and the rest of the classes override their most direct superclass's DoSomething.

The problem with your code is that you left out the virtual key word in all the other classes. Virtual once is not virtual always, but it should be.
Last edited on
Thanks for the info
Mmm, so if I want to implement the same virtual function on all the derived classes, should I write the virtual keyword in every class' function?
Last edited on
The problem with your code is that you left out the virtual key word in all the other classes. Virtual once is not virtual always, but it should be.


Actually it is. Putting virtual on one of the functions means it is virtual in all derived classes, even if you don't put it there.
LB wrote:
Virtual once is not virtual always
¿? It is. (at least downstream)
What I actually want to do is to overload in all derived classes the virtual member function from Parent, but I don't know if I did it correctly.


The way I see it, there are 3 situations:

1. You want to have a function that is the same for all the derived classes regardless. In this case it is just a function in the base class that is inherited - make it protected. There is no virtual keyword.
2. You want to have a function that is the same for most of the derived classes, but different for some of them. Use the virtual keyword without the = 0. This means you have the option of redefining the function in a derived class if you want.
3. You want to have a function that will be different for each derived class. Use the virtual keyword with the = 0 as you have done. This is a pure virtual function. This means you must redefine the function in each derived class. An example of this would be a base class called Shape with a pure virtual function called Area, derived classes such as Circle, RegularPolygon and IrregularPoly will all have their own area function definitions.

I apologise if my explanation is overly simplistic.

Edit: Was the output of your program different to what you expected?
Last edited on
@TheIdeasMan:

Actually the output was right.

Umm, I think I should explain a little more what I intended to do: Originally I thought I could have a super class and derive 3 classes from it, because that super class would contain X attributes that every derived class would have (in other words, this was a normal inheritance situation). But while writing my program, I realized that if super class had X attributes, class A would have X + Y attributes, class B would have X + Y + Z attributes, and so on (each derived class would have the same attributes than its immediate parent class and add new attributes of its own).

So I rewrote my program. What I intended to do was to override the Input method that I would use to ask the user for the attributes' values and I thought it would be easier if I just put this method in the first parent and then implement it on every single class down the chain. I would do it this way because each Input method would have an entirely different functionality depending of the class that is calling it (despite they would basically be asking for the same attributes).

The program still works as intended, but as I'm still fairly new to OOP (and C++), I want to make sure I understand how inheritance and polymorphism works so I can use them correctly.

Your explanation helped a lot, and I think my situation fits your 3rd example. However, the explanation you gave about the Area method is a situation where Circle, RegularPolygon and IrregularPoly are all derived from a single class (Shape). In my particular case, I have some kind of a "chain of inheritance", where each derived class derives a new class of its own.
@oldcrow @firedraco @ne555 Nope, at least not for me:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
#include <iostream>
using std::cout;
using std::endl;

struct A
{
    virtual void f(){cout<<"A::f"<<endl;}
};
struct B: A
{
    void f(){cout<<"B::f"<<endl;}
};
struct C: B
{
    void f(){cout<<"C::f"<<endl;}
};
struct D: C
{
    void f(){cout<<"D::f"<<endl;}
};

int main()
{
    D d;
    C &c = d;
    B &b = c;
    A &a = b;

    a.f();
    b.f();
    c.f();
    d.f();
}
D::f
B::f
C::f
D::f
I've been told that this is why you must make destructors virtual when you do virtual inheritance; to make sure they get called correctly.
@oldcrow

Are you aware that you can call base class constructors from a derived class?

So each of the derives class constructors can call any of it's base class constructors - this way you build up the construction step by step.

I am just wondering whether the decorator design pattern might be of help?

http://www.vincehuston.org/dp/decorator.html
Ugh, ok I feel I'm complicating myself with something that can be done easily. OK, I read everyone's suggestions and I think I better check my design again. Thanks everyone for your help.

@TheIdeasMan:
Your link was quite interesting and I feel I could implement something like that in my program, I'll give it a shot. Thanks man.
Last edited on
Topic archived. No new replies allowed.