C ++ Итераторы, интерфейсы и указатели - PullRequest
2 голосов
/ 08 декабря 2010

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

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

Вот интерфейсы и реализации (файл .h).

class Interface{
public:
virtual int method() = 0;
};

class Implementation1 : public Interface{
    public:
    int method(); 
};

class Implementation2 : public Interface{
    public:
    int method();
};

Файл .cpp:

#include "content.h"

int Implementation1::method(){
    return 1;
}

int Implementation2::method(){
    return 2;
}

И моя основная функция:

#include "content.h"
#include <vector>
#include <iostream>

using namespace std;

int main(void)
{
    // create the vector and put elements in it
    vector<Interface*> elements;
    elements.push_back(new Implementation1());
    elements.push_back(new Implementation1());
    elements.push_back(new Implementation2());

    // now iterate on them

    vector<Interface*>::iterator iterator;
    for(iterator = elements.begin(); iterator != elements.end(); ++iterator ){
        *iterator->method();
    }

    return 1;
}

, который выводит компилятор:

main.cpp: In function 'intmain () ': main.cpp: 19: ошибка: запрос для элемента' method 'в' * iterator .__ gnu_cxx :: __ normal_iterator <_Iterator, _Container> :: operator-> с _Iterator = Interface **, _Container = std ::vector> ', который не имеет типа' Interface * '

Есть идеи о том, что я здесь делаю неправильно?

Ответы [ 4 ]

11 голосов
/ 08 декабря 2010

Изменить *iterator->method(); на (*iterator)->method();

Первое разыменовывает возвращение iterator-> method (). Интерфейс * не имеет метода (), он не имеет ничего.

Вы хотите разыменовать итератор, чтобы получить указатель, а затем разыменовать ИТ.

У вас есть то же самое, что и Iterator **, поэтому действуйте соответственно.

2 голосов
/ 08 декабря 2010

+ 1 для Ноа об ошибке компиляции с итератором, это хорошее объяснение.Что касается вашего предыдущего вопроса:

Я немного растерялся, какой тип выбрать для векторного содержимого.Это должен быть указатель?я должен сделать «новую реализацию ()»?

Да, это должен быть указатель.Причина проста: вектор типа T хранит (и владеет) только элементы типа T , а не подтипы - и для этого есть веские причины (что, если подкласс имел другой размер?).1009 *

Поэтому вы должны где-то хранить объекты и держать указатели в векторе.На самом деле, хранить их в бесплатном магазине через operator new - самый простой вариант.

Если вы хотите, чтобы ваша жизнь была немного проще, вы можете использовать boost::ptr_vector для своих целей.

0 голосов
/ 08 декабря 2010

Нет ничего недопустимого в том, что вы сделали, но создание вектора необработанных указателей, как правило, плохая идея, вы должны использовать указатель принудительного владения («умный» указатель), такой как shared_ptr. И вам также не нужно отменять ссылку на итератор, он должен просто предложить -> method () напрямую. Тем не менее, я не вижу ничего напрямую не компилируемого с этим кодом, за исключением, возможно, вашего *iterator->method(), потому что в прошлый раз, когда я проверял де-ссылку, действительно низкий приоритет, и вы можете делать *(iterator->method()), что не компилируется.

0 голосов
/ 08 декабря 2010

попробуй (*iterator)->method();

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