Проблема с std :: vector - PullRequest
       5

Проблема с std :: vector

1 голос
/ 24 ноября 2010

Добрый день, люди, я застрял с глупой проблемой C ++.

Допустим, у меня есть итератор it1, который проходит через значения вектора, содержащего указатели на класс, мы назовем его C:

std::vector<C*>::iterator it1;

Но C не одинок:у него есть много подклассов, которые имеют одни и те же атрибуты и методы, которые я ищу с ним1, хотя их реализации могут отличаться или не различаться.Что мне делать, если я хотел, чтобы итератор работал с элементами (или, что лучше, с указателями) не только класса C, но и его дочерних элементов?

То, что я думал, было чем-то, использующим шаблоны, хотя это сделало бы итерации небезопасными, так как я не знаю, как ограничить шаблон только C и его подклассами.Любые предложения?

Редактировать: да, я говорил о рекурсивной структуре данных.

Edit2: Ну, похоже, это не ошибка итератора в конце концов.Мой код работал нормально, я задал вопрос, потому что собирался внести в него изменения, и я не был уверен, что делать.Извините, если это было неясно.

Ответы [ 4 ]

2 голосов
/ 24 ноября 2010

Это прекрасно работает:

class C
{
    public:
       virtual void WhoAmI() { std::cout << "C\n"; }
};
class D: public C
{
    public:
       virtual void WhoAmI() { std::cout << "D\n"; }
};

int main()
{
    C                  cObject;
    D                  dObject;
    std::vector<C*>    data;
    data.push_back(&cObject);
    data.push_back(&dObject);

    std::vector<C*>::iterator it1;

    for(it1 = data.begin(); it1 != data.end(); ++it1)
    {
        (*it1)->WhoAmI();
    }
}
2 голосов
/ 24 ноября 2010

Я думаю, я знаю, что вы имеете в виду. C - это ваш базовый класс, и, скажем, A и B являются производными от C. Но есть функции A и / или B, которых нет в C, вы это имеете в виду? В этом случае вам придется понизить значение *it до A* или B*. Если это должно быть сделано в исключительных случаях, тогда хорошо, в противном случае вы должны изменить дизайн ...

1 голос
/ 24 ноября 2010

Пока вы вызываете только (виртуальные) методы, определенные в общедоступном интерфейсе класса C, наследование и динамическое связывание позаботятся обо всем за вас.Так что если у вас есть, например,

class C {
public:
   virtual oid doit() { std::cout << "I am a C object" << std::endl; }
};

class D : public C {
public:
    void doit() { std::cout << "I am a D object" << std::endl; }
};

int main()
{
   C c;
   D d;
   std::vector<C*> cs;
   cs.push_back(&c);
   cs.push_back(&d);

   vector<C*>::iterator ci;
   for (ci = cs.begin(); ci != cs.end(); ci++) {
      (*ci)->doit();
   }
}

Итератор обращается к каждому указателю, затем вызывает функцию doit () для каждого объекта, к которому получают доступ через указатель, - но вступает в действие динамическое связывание, чтобы решить, какая версия doit() функция вызывается в зависимости от типа объекта во время выполнения.

1 голос
/ 24 ноября 2010

Вектор :: iterator будет работать только с вектором . Кто-то может создавать другие итераторы, но они не будут работать с вашей структурой. И основываясь на полиморфизме, вектор :: iterator может «указывать» на любой подкласс C.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...