2012-03-17 70 views
5

我真的想成为一个更好的程序员,并且制作更多的模块化,有组织的代码。用C++编写一个简单的面向对象的图形

作为一个练习,我试图在C++中用STL做一个非常简单的Graph类。在下面的代码中,我的Node对象不能编译because the commented line results in a reference to a reference in STL

#include <set> 

class KeyComparable 
{ 
public: 
    int key; 
}; 

bool operator <(const KeyComparable & lhs, const KeyComparable & rhs) 
{ 
    return lhs.key < rhs.key; 
} 

class Node : public KeyComparable 
{ 
public: 
    // the following line prevents compilation 
    // std::set<Node &> adjacent; 
}; 

我想边缘存储在set(由key),因为它允许通过键快速去除的边。如果我要存储list<Node*>,那可以正常工作,但不允许通过key快速删除。

如果我使用std::set<Node>,通过边缘所做的更改只会改变本地副本(实际上并不是相邻的Node)。如果我使用std::set<Node*>,我不相信<运算符将工作,因为它将在指针本身上运行,而不是它们索引的内存。

我认为包装引用或指针在另一个类,可能是我的KeyComparable类(根据链接的页面,这是如何提升处理它)。

或者,我可以存储std::list<Node*>std::map<int, iterator>' of locations in the std :: list`。我不确定在更改列表时迭代器是否会保持有效。

以前,这里的一切都只是指针,我会手动处理所有的数据结构。但我真的很想停止使用我使用的每种语言编程C -style,并且实际上成为一名优秀的程序员。

你认为是什么最好方式来处理这个问题?非常感谢。

回答

9

正如你所推断的,你不能在STL容器中存储引用,因为存储的项目的要求之一是它们是可分配的。这与你为什么不能在STL容器中存储数组的原因是一样的。如果没有至少一个用户定义的类型,您也不能重载运算符,这使得看起来您不能在STL类中存储指针时进行自定义比较...

但是,您仍然可以使用std::set的指针,如果你给set自定义比较函子:

struct NodePtrCompare { 
    bool operator()(const Node* left, const Node* right) const { 
     return left->key < right->key; 
    } 
}; 

std::set<Node*, NodePtrCompare> adjacent; 

而且像你想你仍然key得到快速清除。

+0

+1好答案。除了比函数指针更好的语法之外,是否还有将比较函数包装在结构中的其他好处? – user 2012-03-18 02:05:34

+0

@Oliver不是我所知道的,只是这种情况下唯一的方法。尽管可以的话,我更喜欢全局可访问的'operator <',因为它可以在不需要实例化'struct'的情况下进行比较。 – 2012-03-18 04:09:58