Я пишу программу, которая имеет множество вспомогательных функций Directed Graph, чтобы лучше понять C++. Один из центральных объектов называется Node, у которого есть функции-члены, помогающие вычислять расстояние между узлами. Я пытаюсь лучше понять использование шаблонов С++ в ООП-дизайне.
Вот краткий снимок класса Node
class Node {
friend void swap(Node & first, Node & second) {
using std::swap;
swap(first.name, second.name);
}
public:
Node(std::string val);
Node(const Node & copy);
Node & operator = (Node copy) {
swap(*this, copy);
return *this;
}
bool operator < (Node & rhs) const {
return (size < rhs.size);
}
bool operator > (Node & rhs) const {
return (size > rhs.size);
}
bool insertEdge(Node * dest, int distToNode);
// I'd like for this return type to not be tied to an int
// Especially if weights were represented as floats or doubles
int findTravelDistance(Node * const & toNode) const;
int findTravelDistance(std::queue<Node *> * const & nodeRoute) const;
// Mutators
void setNodeName(const std::string nameToSet);
std::string getNodeName() const;
void setNodeSize(const int size);
int getNodeSize() const;
// Misc
void toString() const;
// Constants
static const bool ALLOW_CIRCULAR;
~Node();
protected:
private:
int size;
std::string name;
// Here int represents the weight of the edge. I would like it to be able to be
// declared as an int, float, long, or double etc...
std::map<Node *, int> * travelEdges;
}; // end class
} // end namespace
По мере того, как я создаю этот класс, чтобы включить в него больше функций, я не могу понять, как сделать мои функции более адаптируемыми. Например, посмотрите на функции findTravelDistance.
Я хотел бы, чтобы тип возвращаемого значения, представляющий вес, не зависел от типа, а значение упорядоченной структуры данных карты не зависело от типа. Как это реализовано в настоящее время, пользователь может объявить только тип int для веса. Я понимаю, что могу приступить к перегрузке функций. Но я чувствую, что это было бы слишком избыточно и явным нарушением принципа DRY. Если бы мне пришлось изменить работу этой функции, мне пришлось бы менять ее для каждой перегрузки. Так что моя интуиция подсказывает мне, что я должен использовать шаблоны C++. Поскольку я новичок в шаблонах, я борюсь с тем, где его объявить. Если я сделаю свои функции шаблона функций поиска и просто верну общий тип..
template<class T>
T findTravelDistance(std::queue<Node *> * const & nodeRoute) const;
Это решит мою проблему там. Но это не устраняет проблему, когда базовая структура данных карты, представляющая ребра, может содержать только целые числа. Моей следующей мыслью было объявить шаблон класса.
template<class T>
class Node { ... }
Но мне это тоже показалось странным. Это означало бы, что объявление и инициализация будут выглядеть примерно так
Node<float> * n = new Node<float>("N");
Если бы я был пользователем своей программы, я бы не стал сразу ассоциировать Node с типом float, представляющим веса ребер.
Итак, как лучше всего использовать шаблон в этом случае? Или использование шаблона здесь даже правильный путь? Возможно, мой дизайн класса с самого начала ошибочен и не очень C++'esk. Любая обратная связь здесь очень ценится.