Если сомневаетесь, бросайте шаблоны в проблему, пока она не сдастся:
template <typename N, typename E>
class Graph {
std::vector<N> nodes;
std::vector<E> edges;
};
typedef Graph<VisNode, VisEdge> VisGraph;
typedef Graph<RouteNode, RouteEdge> RouteGraph;
Вы потеряете наследование (RouteGraph больше не наследует от VisGraph), но это нормально в C ++ для типов контейнеров, а Graphчто-то вроде контейнера.Однако вы можете сохранить наследование между Node -> VisNode -> RouteNode.
Поскольку предполагается, что узлы и ребра имеют совпадающие типы, вы можете пойти еще дальше и дать Graph единственный параметр шаблона, который сам по себеявляется классом, содержащим типы ребер и узлов как typedefs.Но я не уверен, что оно того стоит.
Редактировать
Поскольку вы хотите последовательно добавлять функции, вы можете сохранить форму наследования, но потерять полиморфизм:
template <typename N, typename E>
class GraphImpl {
std::vector<N> nodes;
std::vector<E> edges;
};
template <typename N, typename E>
class VisGraphImpl : public GraphImpl<N, E> {
// constructors
// extra functions
};
template <typename N, typename E>
class RouteGraphImpl : public VisGraphImpl<N, E> {
// constructors
// extra functions
};
typedef GraphImpl<Node, Edge> Graph;
typedef VisGraphImpl<VisNode, VisEdge> VisGraph;
typedef RouteGraphImpl<RouteNode, RouteEdge> RouteGraph;
Может быть, есть и лучший способ, объединяя эти дополнительные функции в разумные миксины и используя CRTP:
template<typename Derived>
class VisFunctions {
void somfunc() {
myself = static_cast<Derived&>(*this);
// do stuff
}
};
Тогда:
class VisGraph : public Graph<VisNode, VisEdge>, public VisFunctions<VisGraph> {
friend class VisFunctions<VisGraph>;
};
class RouteGraph : public Graph<RouteNode, RouteEdge>, public VisFunctions<RouteGraph>, public RouteFunctions<RouteGraph> {
friend class VisFunctions<RouteGraph>;
friend class RouteFunctions<RouteGraph>;
};
Не уверен, как это 'Я буду искать ваши реальные обстоятельства, хотя.Кстати, если вы не хотите / не нуждаетесь в объявлении друга для дополнительных функций, тогда вам не нужны эти дополнительные функции, чтобы вообще быть его членами - просто сделайте их свободными функциями, которые принимают параметр VisGraph или RouteGraph.