[英]C++ directed graph node with template implementation
我正在编写具有大量“有向图”助手功能的程序,以便对C ++有更深入的了解。 中心对象之一称为节点,它具有成员函数以帮助计算节点之间的行进距离。 我试图更好地理解在OOP设计中使用C ++模板。
这是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 ++。 非常感谢这里的任何反馈。
这是非常干净的代码:)。 欢迎使用C ++!
我相信您要使用模板变量来保持边缘权重。 如下所示:
using std::swap;
template<class Distance>
class Node {
friend void swap(Node & first, Node & second) {
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, Distance distToNode);
// I'd like for this return type to not be tied to an int
// Especially if weights were represented as floats or doubles
Distance findTravelDistance(Node * const & toNode) const;
Distance findTravelDistance(std::queue<Node *> * const & nodeRoute) const;
// Mutators
void setNodeName(const std::string nameToSet);
std::string getNodeName() const;
void setNodeSize(const Distance size);
int getNodeSize() const;
// Misc
void toString() const;
// Constants
static const bool ALLOW_CIRCULAR;
~Node();
private:
int size;
std::string name;
std::map<Node *, Distance> * travelEdges;
}; // end class
另外,我已经将您的using声明移到了类的顶部。 通常,这些文件位于文件的顶部。 您也可以从Parapara C ++ FAQ的圣经中受益,尤其是有关const正确性的部分 。 例如,您的比较器方法应具有const Node&参数。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.