Как "наследовать" итератор из класса STL?

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

Я прочитал несколько связанных вопросов и ответов, и мне довольно легко просто наследовать 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;
}

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

1 ответов


ваша первая проблема в том, что 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 полиморфно через указатель на базу, так просто документ, что никто никогда не должен пытаться сделать это, и вы будете в порядке.

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