34

I have a class structure similar to the following

class A
{
public:
    A(void);
    ~A(void);

    void DoSomething(int i)
    {
        std::cout << "Hello A" << i << std::endl;
    }
};

class B : public A
{
public:
    B(void);
    ~B(void);

    void DoSomething(int i)
    {
        std::cout << "Hello B" << i << std::endl;
    }
};

class Ad : public A
{
public:
    Ad(void);
    ~Ad(void);
};

class Bd : public B
{
public: 
    Bd(void);   
    ~Bd(void);
};

I want to store instances of the derived classes in a container (standard map) as a collection of A*, then iterate through the container and call methods for each instance.

#include "A.h"
#include "B.h"
#include "Ad.h"
#include "Bd.h"
#include <map>
int main(int argc, char** argv)
{
    std::map<int,A*> objectmap;
    objectmap[1] = new Ad();
    objectmap[2] = new Bd();

    for (std::map<int,A*>::iterator itrobject = objectmap.begin();
         itrobject!=objectmap.end(); itrobject++)
    {
        itrobject->second->DoSomething(1);
    }
    return 0;
}

The above code produces the following output.

Hello A1
Hello A1

Where I was expecting

Hello A1
Hello B1

because I was expecting DoSomething in B to hide DoSomething in A, and because I am storing A pointers, I would expect no object slicing (and looking at the object pointer in the debugger shows that the object has not been sliced).

I have tried down casting and dynamic casting the pointer to B, but it slices away the data members of Bd.

Is there any way to call B::DoSomething without casting the pointer to Bd? And if not, if I have many derived classes of B (e.g. Bda, Bdb, Bdc etc), is there some way to use RTTI to know which derived class to cast it to?

jww
  • 97,681
  • 90
  • 411
  • 885
Ian Thompson
  • 644
  • 1
  • 6
  • 11
  • 6
    You need to make that function `virtual`. – Crowman Sep 19 '13 at 02:13
  • 1
    @PaulGriffiths you should make your comment an answer. – helloworld922 Sep 19 '13 at 02:14
  • If I make A::DoSomething virtual, then I will need to implement DoSomething in Ad, correct? – Ian Thompson Sep 19 '13 at 02:15
  • @helloworld922: Good call, added. – Crowman Sep 19 '13 at 02:16
  • I kinda don't understand why folks go to all the effort of typing out a detailed question like this, only to submit it with the exact same title as the previous iterations. Are they scared of search? http://stackoverflow.com/questions/15853031/call-base-class-method-from-derived-class-object?rq=1 – kfsone Sep 19 '13 at 02:17
  • @IanThompson No, only if it was declared purely virtual (sometimes called "abstract" in other languages). Ad is free to use the implementation provided by A if it doesn't need its own implementation. Virtual simply means this function is polymorphic.. – helloworld922 Sep 19 '13 at 02:18
  • @IanThompson: Sorry, I misread your question. No, you don't have to implement virtual functions in every sub class, if you don't, it'll just call the base class function. – Crowman Sep 19 '13 at 02:19

1 Answers1

34

You need to make DoSomething() a virtual function in both classes to get the polymorphic behavior you're after:

virtual void DoSomething(int i) { ...

You don't need to implement virtual functions in every sub class, as shown in the following example:

#include <iostream>

class A {
    public:
        virtual void print_me(void) {
            std::cout << "I'm A" << std::endl;
        }

        virtual ~A() {}
};

class B : public A {
    public:
        virtual void print_me(void) {
            std::cout << "I'm B" << std::endl;
        }
};

class C : public A {
};

int main() {

    A a;
    B b;
    C c;

    A* p = &a;
    p->print_me();

    p = &b;
    p->print_me();

    p = &c;
    p->print_me();

    return 0;
}

Output:

I'm A
I'm B
I'm A

honk
  • 9,137
  • 11
  • 75
  • 83
Crowman
  • 25,242
  • 5
  • 48
  • 56
  • Sorry for the dupe comment. If I make DoSomething virtual in A, then I will need to implement DoSomething in Ad, and all other derived classes of A. I was hoping to avoid that as there are many of them. Is that the only way do achieve this? – Ian Thompson Sep 19 '13 at 02:18
  • 1
    As noted in the comments, you don't have to implement virtual functions in every sub class. Your sub classes will use the implementation in the base class, if you don't implement it in them. – Crowman Sep 19 '13 at 02:21
  • Works in my test project, but not in my actual project. Unresolved external symbol. It must be something else. It is something else. Thanks for your reply. – Ian Thompson Sep 19 '13 at 02:35