2014-01-16 3 views
8

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

Я прочитал несколько связанных вопросов и ответов, и мне очень легко просто наследовать std::vector<std::vector<unsigned int> >, но консенсус в том, что это плохо из-за контейнеров STL, не имеющих виртуальных деструкторов или чего-то еще. Поэтому я решил попробовать и наследовать по композиции. Вот несколько -минимальный пример того, что я пытаюсь достичь:

#include <vector> 
#include <iostream> 

class tableau { 
    private: 
    std::vector<std::vector<unsigned int> > rep; 
    public: 
    using std::vector<std::vector<unsigned int> >::iterator; 
    void push_back(std::vector<unsigned int> const& new_row) { 
     rep.push_back(new_row); 
    } 
}; 

int main() { 
    tableau t1; 
    std::vector<unsigned int> row1(10); 
    std::vector<unsigned int> row2(8); 

    t1.push_back(row1); 
    t1.push_back(row2); 

    tableau::iterator it = t1.begin(); 
    for (; it != t1.end(); ++it) { 
    //display rows of tableau 
    } 
    return 0; 
} 

Но г ++ дает мне ошибку: тип «std::vector<std::vector<unsigned int> >» не является базовым типа для типа «таблицы». Я только начинаю изучать C++, поэтому, пожалуйста, будьте осторожны, если я сделал что-то глупое. Если вы хотите получить больше фактического кода, который я написал, дайте мне знать.

+3

В общем, это очень хороший TestCase. Отлично сработано. :) –

ответ

10

Ваша первая проблема заключается в том, что using не позволяет вам украсть типы из произвольных несвязанных типов (хотя для этого вы можете использовать typedef). Кроме того, у вас нет begin() или end() пользователей.

Решение этих проблем приводит к следующему:

#include <vector> 
#include <iostream> 

class tableau { 
    private: 
    std::vector<std::vector<unsigned int> > rep; 
    public: 
    typedef std::vector<std::vector<unsigned int> >::iterator iterator; 
    void push_back(std::vector<unsigned int> const& new_row) { 
     rep.push_back(new_row); 
    } 
    iterator begin() { return rep.begin(); } 
    iterator end() { return rep.end(); } 
}; 

int main() { 
    tableau t1; 
    std::vector<unsigned int> row1(10); 
    std::vector<unsigned int> row2(8); 

    t1.push_back(row1); 
    t1.push_back(row2); 

    tableau::iterator it = t1.begin(); 
    for (; it != t1.end(); ++it) { 
    //display rows of tableau 
    } 
    return 0; 
} 

Однако, ваш подход означает, что вы будете иметь, чтобы обернуть каждую функцию, которую вы хотите позвонить.

Если бы я был вами, я бы придерживался наследования: хотя совет, который вы цитируете, верен, это не значит, что наследование невозможно. Вы никогда не захотите использовать ваш tableau полиморфно через указатель на базу, поэтому просто документ, который никто никогда не должен пытаться сделать, и все будет в порядке.

(Когда вы используете «композиции» это называется «сочинять». Вы спрашиваете, как «сочинять» вектор.)

+0

Хорошо, концепция компоновки теперь имеет больше смысла, спасибо. Я думаю, что в этом случае я просто придерживаюсь наследования. –

+0

@Joseph: Я думаю, что это мудро. –

+0

+1 Наследование контейнеров не так уж плохо, как некоторые люди пытаются это сделать. – jrok

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