Нужна помощь с картой (c ++, STL) - PullRequest
3 голосов
/ 14 мая 2010

На самом деле я новичок в C ++. Я попробовал что-то (на самом деле контейнер карт), но это не сработало так, как я предполагал ... Перед публикацией кода я вскоре объясню.

Я создал 3 класса:

ClassA ClassDerivedA ClassAnotherDerivedA

Два последних являются производными от "ClassA".

Далее я создал карту:

  map<string,ClassA> test_map;

Я поместил некоторые объекты (из типов ClassDerivedA и ClassAnotherDerivedA) в карту. Имейте в виду: сопоставленное значение относится к типу "ClassA". Это будет работать только из-за полиморфизма. Наконец, я создал итератор, который работает над моей картой и сравнивает вводимые пользователем данные с моими ключами на карте. Если они совпадают, он вызовет определенный метод с именем "printOutput".

И есть проблема: Хотя я объявил «printOutput» как «виртуальный», единственный вызванный метод - метод из моего базового класса, но почему? и вот код:

#include <iostream>
#include <map>

using namespace std;

class ClassA
{
    public:
        virtual void printOutput() { cout << "ClassA" << endl;      }
};

class ClassDerivedA : public ClassA
{
    public:
        void printOutput() { cout << "ClassDerivedA" << endl;       }
};

class ClassAnotherDerivedA: public ClassA
{
    public:
        void printOutput() { cout << "ClassAnotherDerivedA" << endl;        }
};

int main()
{
    ClassDerivedA class_derived_a;
    ClassAnotherDerivedA class_another_a;


  map<string,ClassA> test_map;
    test_map.insert(pair<string,ClassA>("deriveda", class_derived_a));
    test_map.insert(pair<string,ClassA>("anothera", class_another_a));

    string s;

    while( cin >> s )
    {
    if( s != "quit" )
    {
        map<string,ClassA>::iterator it = test_map.find(s);
      if(it != test_map.end())
        it->second.printOutput();
    }
    else
      break;
    }

}

Ответы [ 3 ]

13 голосов
/ 14 мая 2010

Проблема в нарезке. Вы храните ClassA значения на вашей карте. Когда вы сохраняете экземпляры производных классов на карте, они разбиваются на ClassA объекты. Вам нужно хранить указатели на карте вместо значений.

См. Дополнительную информацию о нарезке: Что такое нарезка объектов?

4 голосов
/ 14 мая 2010

Вы испытываете " нарезка ". Чтобы виртуальные функции работали правильно, вам нужно вызывать их с помощью указателя или ссылки. Другими словами, ваш map должен содержать указатели на ClassA:

map<string, ClassA *> test_map

Пожалуйста, не забудьте delete, когда вы закончите, или используйте умные указатели.

Подробнее о нарезке: здесь , здесь и здесь

4 голосов
/ 14 мая 2010

C ++ не является Java. Вы не можете хранить производный тип в переменной базового типа. Например:

Base b = Derived();

будет хранить только базовую часть производного в переменной b. Чтобы получить полиморфное поведение, вам нужно использовать указатели и динамически создавать производный класс:

Base * b = new Derived();

То же самое касается контейнеров C ++ - вам нужно:

map <string, Base *> m;

Все это должно быть освещено в каждом вводном учебнике по C ++ - какой из них вы используете?

...