2012-06-19 2 views
1

У меня есть два (не связанных) класса. Первый «Точка»:Является ли этот пример множественного наследования приемлемым в C++?

typedef std::complex<double> complex_number; 

class Point 
{ 
public: 
    Point(const complex_number &affix); 

    const complex_number & get_affix() const; 
    void set_affix(const complex_number & new_affix); 

    // etc 
private: 
    complex_number affix_; 
}; 

(Кстати, извините за вопрос этот несвязанный вопрос, но где это правильное место, чтобы положить мои определения типа здесь, верхняя часть моего файла point.hpp, ? «хорошая практика»)

Второй является «Abstract_Vertex» (это значит быть частью абстрактного графа позже):

typedef int vertex_label; 

class Abstract_Vertex 
{ 
public: 
    Abstract_Vertex(const vertex_label &label); 

    const vertex_label & get_label() const; 
    const vertex_label & get_neighbor_label(const int &index) const; 
    void set_label(const vertex_label &new_label); 

    bool is_neighbor_label(const vertex_label &label) const; 

    // etc 
protected: 
    vertex_label label_; 
    std::vector<vertex_label> neighbor_labels_; 
}; 

Теперь я хочу, чтобы создать третий класс, «Plane_Vertex» (вершина, расположенная где-то в плоскости). Я размышлял два способа сделать это:

  1. Множественное наследование: класс Plane_Vertex наследует от точечных и Vertex, и не имеет каких-либо членов

  2. класс Plane_Vertex наследует только от Vertex и имеет частный Point point_ участник.

Конечно, я мог бы легко избежать множественного наследования и просто пойти на вариант 2., но я хороший маленький добросовестный C++ обучаемый, и я хочу знать, что «хорошая практика» была бы в моей ситуации.

Благодарим вас за понимание!

+0

Имеет ли смысл иметь смысл рассматривать «Plane_Vertex» как «точку»? Если это так, то множественное наследование. – jxh

+0

Возможный дубликат [Предпочитаете состав над наследованием?] (Http://stackoverflow.com/questions/49002/prefer-composition-over-inheritance) –

+0

Проверьте дублированный вопрос, с которым я связан; у которого есть действительно хорошие ответы на композицию против наследования, которая по сути вас интересует. –

ответ

1

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

Поскольку дизайн компрометирует, я хочу указать основные отличия от моей точки зрения.

Связанные/несвязанные типы вершин

В шаблоне подхода, различные конкретизации совершенно разные типы. Это означает, что Vertex<int> и Vertex<Point> не связаны. С другой стороны, в полиморфном подходе выше всех вершин IntVertex, PointVertex ... являются объектами AbstractVertex: вы можете комбинировать их в контейнерах и подключать их или использовать их взаимозаменяемо в коде, который может использовать AbstractVertex. Независимо от того, является ли это ограничением или преимуществом любого из этих подходов, это опять же дизайнерское решение. Я предпочитаю, чтобы типы были несвязанными, поскольку я не чувствую, что вы должны смешивать эти типы.

Количество кода, чтобы написать

В шаблоне подхода вы реализуете шаблон, а затем вы просто экземпляр, в полиморфной подходе необходимо предоставить новый класс для каждого возможного элемента, который вы хотите включить в a graph

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

+0

Ваш ответ очень интересен для меня из-за того, что я делаю позже: у меня есть класс шаблонов Graph , членом которого является вектор , где T должен быть создан как абстрактный_Vertex или Plane_Vertex (или, в факт, CP_Vertex, третий вид). Как вы думаете, что играет в пользу того или иного варианта? – Seub

+0

Подумав об этом в течение нескольких минут, IMHO, единственный недостаток подхода к шаблону в этом параметре заключается в том, что, хотя мой Plane_Vertex станет Vertex , а мой CP_Vertex станет Vertex (это нормально!), Мой Abstract_Vertex будет больше походите на Vertex ! Это раздражает. – Seub

+0

@ user1367124: Если вы реализуете подход к шаблону, тогда не будет 'AbstractVertex', вопрос в том, нужно ли в вашем дизайне использовать« PointVertex »и« CircleVertex »полиморфно как« AbstractVertex », или это даже делает смысл или нет. Если вы выберете шаблонный подход, я бы ожидал, что тип 'T' в' Graph 'будет тем же типом экземпляра, который вы использовали бы с помощью' Vertex '. То есть, вы хотите, чтобы 'Graph ' that * содержит * 'Vertex ' ... * * переменная *, которую вы хотите использовать, - это то, какие данные хранятся ('Point'), а не как построить график (' Vertex '). –

0

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

Причины:

  1. Вы избегаете diamond problem.
  2. Держите дизайн как можно более простым - после нескольких уровней, множественное наследование действительно может быть болью следовать и поддерживать.
  3. Как правило, проще проверить, что ваш класс удовлетворяет принципам хорошего дизайна, когда вы не используете множественное наследование.
  4. Composition и/или aggregation обычно обеспечивают хорошие или лучшие подходы.
  5. Проще проверить свои классы.

Этого должно быть достаточно, чтобы вы начали. На посту, с которым связан Джон Кейдж, есть намного больше мудрости.

Поэтому, чтобы ответить на ваш вопрос: похоже, у вас нет достаточной причины использовать множественное наследование. Используйте композицию.

+0

Множественное наследование - один из способов сделать композицию на C++. –

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