2016-09-20 4 views
2

Мы создали три типа данных STL и STL-наследуется для использования в алгоритме кластеризации:удалить() Обработка STL Multi-Inheritance

typedef std::vector<double>Point; // A list of parameters (a single observation) 

struct Cluster : std::list<Point> { // A list of Points 
    // Additional member variables 
    Point centroid; 
    bool centroid_valid; 
    bool sort_valid; 
    // Cluster functions omitted 
}; 

struct Universe : std::list<Cluster> { // A list of Clusters 
    // No member variables 
    // Universe functions omitted 
}; 

Это попытка полностью использовать STL так ничего не new в существование. Озабоченность, что связано с характером субординированного функциональности STL, а именно:

Если бы мы remove()Cluster элемент из Universe списка, бы STL обрабатывать не только удаление (и управление памятью) всех Point с в Cluster, подлежащем удалению, а также удаления всех переменных-членов?

Примечание: все функции-члены относительно просты, без статических операций.

+3

Да. Но неплохо наследовать стандартные контейнеры. Вселенная * имеет * несколько кластеров, но это еще не все, что есть *. –

+1

Эти стандартные контейнеры на самом деле не предназначены для наследования. –

+1

Вот еще одна причина не наследовать: предположим, что в будущем вам нужно будет изменить хранилище кластера, чтобы быть, скажем, Eigen-матрицей, чтобы операции можно было объединить и оптимизировать по всей матрице. Вы не хотите, чтобы ваш интерфейс был принудительно подключен к интерфейсу STL, но вместо этого соответствовал вашему типу данных: 'Cluster :: AddPoint()' например. – Peter

ответ

3

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

Да, это произойдет потому, что он работает с объектами кластера и удаляет его, удаляя все его поля. Но наследование от стандартных контейнеров считается плохой практикой, потому что у них нет виртуального деструктора. Лучше хранить список Points в кластере как свойство.

+0

Спасибо - можете ли вы расширить то, что вы имеете в виду: «Лучше хранить список очков в кластере как свойство?» – Miller

+1

@Miller означает, что лучше агрегировать, а не наследовать. – Slava

1

неправильно:

typedef std::vector<double>Point; // A list of parameters (a single observation) 

struct Cluster : std::list<Point> { // A list of Points 
    // Additional member variables 
    Point centroid; 
    bool centroid_valid; 
    bool sort_valid; 
    // Cluster functions omitted 
}; 

право:

typedef std::vector<double>Point; // A list of parameters (a single observation) 

struct Cluster { // A list of Points 

    std::list<Point> points; 

    // Additional member variables 
    Point centroid; 
    bool centroid_valid; 
    bool sort_valid; 
    // Cluster functions omitted 
}; 

При наследовании от класса, вы по своей природе гарантирует, что все его функции-члены будут вести себя здраво при вызове против своего класса.

Проблема в том, что «дополнительные переменные-члены» представляют собой кешированные наблюдения точек. Если вы erase или insert точка, эти кэшированные наблюдения будут не синхронизированы, и поэтому не соответствует.

Если вы хотите, чтобы кластер имел тот же интерфейс, что и std :: list, вы должны реализовать этот интерфейс, вызвать в член points и обновить (или отметить как недопустимые) кэшированные наблюдения.

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