2010-11-24 3 views
1

Добрый день, Я застрял в глупой проблеме на C++.Проблема с std :: vector

Скажем, у меня есть итератор, называемый it1, который идет через значение вектора, содержащий указатели на класс, мы будем называть это C:

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

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

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

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

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

+0

Вы говорите рекурсивную или плоскую структуру данных? Вы используете термины, которые делают различие запутанным. – robert 2010-11-24 08:25:53

+1

Он уже ограничен С и его детьми. – 2010-11-24 08:26:41

ответ

2

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

1

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

2

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

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

До тех пор, пока вы используете только виртуальные методы, определенные в открытом интерфейсе класса 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(); 
    } 
} 

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

Смежные вопросы