2014-06-01 2 views
0

Я читал, что скрытие фактического типа контейнера, используемого в классе, - это хорошо. Это делает случайным (или преднамеренно) написание кода, который соответствует фактическому типу контейнера (который может меняться и прерывать предыдущий код), и, следовательно, код более надежный.Скрытие реализации контейнера STL от пользователей класса

Таким образом, это означает, что это не очень хорошая идея; Если изменения реализации от std::vector до std::list вещей сломаются:

class MyType { 
public: 
    const std::vector<MyType*>& GetChildren() const; 
    std::vector<MyType*>& GetChildren(); 

    const std::vector<MyType*>::size_type GetChildCount() const; 
    std::vector<MyType*>::size_type GetChildCount(); 
private: 
    MyType* _parent; 
    std::vector<MyType*> _children; 
}; 

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

class MyType { 
public: 
    typedef std::vector<MyType*> ChildContainer; 
    typedef ChildContainer::size_type ChildContainerSize; 

    const ChildContainer& GetChildren() const; 
    ChildContainer& GetChildren(); 

    const ChildContainerSize GetChildCount() const; 
    ChildContainerSize GetChildCount(); 
private: 
    MyType* _parent; 
    ChildContainer _children; 
}; 

Вопрос: Есть ли способ, чтобы скрыть базовый тип контейнера, так что это будет трудно для пользователя код вокруг него короткое оберточной контейнер STL в потенциально плохо написано и не-необходимой обертке ?

+0

Вы имеете в виду, как скрыть базовый контейнер? Как насчет итераторов? – 4pie0

+2

Вместо предоставления методам getter 'GetChildren()' предоставляет свои собственные операции для добавления/обновления/удаления и повторения элементов _child_. –

+1

См. [Эту статью о стирании типа *] (http://www.artima.com/cppsource/type_erasure.html). – juanchopanza

ответ

-1

Вы должны использовать typedefs и итераторы. Затем, если вы хотите изменить контейнер, вы можете, потому что пользователи зависят только от итераторов. Люди всегда могут сломать его, если захотят, но вы разоблачаете простой способ НЕ ломаться.

class MyType { 
public: 
    typedef std::vector<MyType*> ChildContainer; 
    typedef ChildContainer::size_type ChildContainerSize; 
    typedef std::vector<MyType*> ChildContainerIter; 
    typedef std::vector<MyType*> ChildContainerCIter; 

    const ChildContainerCIter GetChildrenBegin() const { return _children.begin(); } 
    ChildContainerIter GetChildrenBegin() { return _children.begin(); } 
    const ChildContainerCIter GetChildrenEnd() const { return _children.end(); } 

    const ChildContainerSize GetChildCount() const; 
private: 
    MyType* _parent; 
    ChildContainer _children; 
}; 

И нет никакого способа полностью скрыть его. Компилятор должен знать, какой тип это, когда их код компилируется.

+0

Итераторы разных контейнеров не всегда поддерживают одни и те же операции. Таким образом, это не позволяет вам изменять контейнер без нарушения кода клиента. В статье, приведенной в комментарии, представлены некоторые решения этой проблемы. – juanchopanza

+0

Его вопрос о том, чтобы написать плохо написанную обертку, заставил меня подумать, что он хотел что-то в этом стиле и не слишком сложно. Это решение является большим шагом от раскрытия объекта, потому что итератор является LOT более взаимозаменяемым, чем контейнеры. – Michael

0

Иногда у вас нет выбора, но для отображения основных типов контейнеров. Например, для случайно доступных контейнеров, таких как std :: vector v, я могу выполнять сортировку (v.begin(), v.begin() + 10); тогда как для std :: list li я могу делать только li.sort(), как вы можете скрыть тип контейнера и использовать только итераторы? Эти итераторы полностью несовместимы. Кроме того, тип контейнера является одним из самых фундаментальных соображений при разработке программного обеспечения, почему вы должны думать о будущей возможности изменения типа контейнера? Это обычно означает плохое проектирование и полный римейк программного обеспечения.

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