Подтвердить что ты не робот

Как вызвать метод производного класса из указателя базового класса?

У меня есть структура класса, аналогичная следующей

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);
};

Я хочу хранить экземпляры производных классов в контейнере (стандартная карта) в виде коллекции A *, затем перебирать контейнер и методы вызова для каждого экземпляра.

#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;
}

Вышеприведенный код выводит следующий результат.

Hello A1
Hello A1

Где я ожидал

Hello A1
Hello B1

потому что я ожидал DoSomething в B, чтобы скрыть DoSomething в A, и поскольку я сохраняю указатели A, я бы не ожидал никакого объекта slicing (и просмотр указателя объекта в отладчике показывает, что объект не был нарезан).

Я попробовал кастинг и динамический кастинг указателя на B, но он отсекает элементы данных Bd.

Можно ли вызвать B:: DoSomething, не указав указатель на Bd? И если нет, если у меня есть много производных классов B (например, Bda, Bdb, Bdc и т.д.), есть ли какой-то способ использовать RTTI, чтобы узнать, какой производный класс его отличает?

4b9b3361

Ответ 1

Вам нужно сделать функцию DoSomething() a virtual в обоих классах, чтобы получить полиморфное поведение, которое вы после:

virtual void DoSomething(int i) { ...

Вам не нужно реализовывать виртуальные функции в каждом подклассе, как показано в следующем примере:

#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;
}

Вывод:

Я нахожусь Я В

Я А