带有模板实现的C ++定向图节点

时间:2013-08-07 03:39:40

标签: c++ oop templates directed-graph

我正在编写具有大量Directed Graph辅助函数的程序,以便更深入地理解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 ++模板。由于我是模板的新手,我正在努力争取它的声明。如果我使用find函数模板函数并返回泛型类型..

template<class T>
T findTravelDistance(std::queue<Node *> * const & nodeRoute) const;

那将解决我的问题。但是,它并没有解决表示边缘的底层地图数据结构只能保持整数的问题。我的下一个想法是宣布一个类模板..

template<class T>
class Node { ... }

但这对我来说似乎也很奇怪。这意味着声明和初始化看起来像

Node<float> * n = new Node<float>("N");

如果我是我的程序的用户,我不会立即将Node与表示边权重的浮点类型相关联。

那么在这种情况下,模板的最佳或适当用法是什么?或者在这里使用模板甚至是正确的路径?有可能我的课程设计有缺陷,而不是非常C ++的esk。这里的任何反馈都非常感谢。

1 个答案:

答案 0 :(得分:1)

这是非常干净的代码:)。欢迎来到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

作为奖励,我已将您的使用声明移至课程顶部。通常这些都位于文件的顶部。你也可以看一下Parashift C ++ FAQ的神圣经文,尤其是section on const correctness。例如,你的比较器方法应该有const Node&amp;参数。