Итератор шаблона класса и сокрытие информации
Предполагая, что у нас есть реализация шаблонного класса для матрицы. Я хочу представить матрицу std::vector
типа T
,
Теперь я хочу вернуть итератор матрицы, вернув итератор вектора. Для этого я увидел, что с помощью ключевого слова typename
требуется в public
раздел:
typedef typename std::vector<T>::iterator iterator.
Во-первых, я не понимаю, почему typename
требуется здесь.
Во-вторых, каждый может видеть, что я использую std::vector
представлять матрицу. Что я могу сделать, чтобы предотвратить раскрытие этой информации.
Как я могу достичь этой цели, не раскрывая матричное представление?
3 ответа
Во-первых, вам нужно имя типа, поскольку вы используете зависимый тип. для получения дополнительной информации см. Где и почему я должен поставить ключевые слова "template" и "typename"?
Для второй части вы можете сделать две typedefs. Один в частном разделе, который
typedef typename std::vector<T> container;
И тогда в публичном разделе вы могли бы сделать
typedef typename container::iterator iterator;
И вы можете увидеть, как это компилируется здесь
Во-первых, я не понимаю, почему typename включено сюда.
typename
сообщает компилятору, что iterator
это действительно тип, а не член, например, который будет выглядеть точно так же. Вы должны уточнить это при работе с шаблонами, потому что в общем случае на этом этапе компилятору не хватит информации, чтобы заметить разницу.
Во-вторых, каждый может видеть, что я использую вектор для представления матрицы, что я могу сделать, чтобы предотвратить раскрытие этой информации.
Хотя каждый может видеть, что вы используете вектор, это не является коммерческой тайной. Вы предоставляете typedef для использования внешним миром, подчеркивая, что вектор - это просто деталь реализации, и если они этого не делают, они заслуживают того, что приходит, по моему мнению.
Чтобы подчеркнуть это, vector<T>::iterator
также является typedef, и в некоторых компиляторах это означает разные вещи, когда вы компилируете с разными флагами. Иногда вы можете найти его и использовать T*
везде, но когда код в конечном итоге сломается, вы действительно будете жаловаться на разработчиков стандартной библиотеки?
Я не думаю, что вы могли бы скрыть это лучше: компилятор должен знать, что такое итератор.
Вы должны включить typename
здесь, потому что есть предполагаемый тип, T
, подарок. Об этом спрашивали и отвечали здесь.
Что касается вашего второго вопроса, вы на самом деле не выставляете здесь представление о классе; пользователь вашего класса не должен понимать, что базовое представление Matrix является std::vector
для того, чтобы использовать свой класс. Информация на самом деле будет доступна только в том случае, если пользователь попытается ее найти (например, из-за ошибки компиляции). Даже если вы определили свой собственный итератор, пользователь все равно может просто посмотреть на ваш исходный код.
Наконец, если вы используете C++11, лучший способ сделать то же самое - использовать псевдонимы:
using iterator = typename std::vector<T>::iterator;
Нет непосредственного преимущества в этом случае, но хорошо, чтобы войти в эту привычку.