3

我找到了一个用于 Graphs 的开源类库。当我将它包含在我的项目中时,它有很多错误,我试图修复它们。但是有一个我无法解决的编译错误。

基类:

template <typename K, typename W, typename T>
class _base_graph
{
//... 

protected:
    std::map<K, T> nod;
    std::list<edge> edg;
};

派生类:

template <typename K, typename T = void*>
        class graph : public _base_graph<K, void*, T>
{
//...
public:
    void add_edge(const K& k1, const K& k2);
};

方法体:

template <typename K, typename T>
void graph<K, T>::add_edge(const K& k1, const K& k2)
{
    if (nod.find(k1) == nod.end() || nod.find(k2) == nod.end()) // <-- error!!
        throw std::string("add_edge: Node does not exist");

    // ...
}

但是我的 gcc 编译器向我显示了一个错误:

错误:未在此范围内声明“点头”

您可以在此在线编译器中找到并测试 mycode 。

4

2 回答 2

8

你需要

this->nod.find(k2);

或者

_base_graph<K, void*, T>::nod.find ....;

基类和派生类是模板,在您的代码中是一个非依赖名称,因此在's 声明nod点查找。graph这是两阶段查找的第一阶段。在这个阶段,编译器(只要它遵循标准的名称查找规则)是不可能知道什么nod意思的,因为它直到第二阶段才考虑基类。所以有必要告诉编译器nod应该在第二阶段查找。为此,我们nod使用上述形式之一明确告诉它在基类中。

这种行为的原因是,在派生类的定义点,它不应该知道_base_graph<K, void*, T>::包含什么,以允许添加甚至隐藏名称的模板的特化。因此,当所有信息都可用时,上面的技巧确保在派生类的实例化点查找名称。

总之,这里有两个问题:

  1. nod不是从属名称,因此将在第一阶段查找。
  2. 声明的基类模板nod直到第二阶段才可用,因此无法解析名称。

通过使用this->nodor _base_graph<K, void*, T>::nod,我们显式地处理依赖名称,强制在第二阶段进行查找。

请参阅此处的第 7 至 10 点。

感谢@DavidRodriguez-dribeas 澄清了两阶段查找的一些细节。

于 2012-11-13T11:08:45.707 回答
3

nod是依赖基础的成员(依赖于模板参数的基础)。您要么需要使用基础名称来限定调用,例如,_base_graph<K, void*, T>::nod要么使用this->nod.

using _base_graph<K, void*, T>::nod或者,您也可以在函数或类范围内引入名称。

于 2012-11-13T11:11:33.117 回答