受保护的成员对于派生类是未知的

时间:2012-11-13 11:07:15

标签: c++

我找到了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编译器显示错误:

  

错误:未在此范围内声明'nod'

您可以在this在线编译器中找到并测试我的代码。

2 个答案:

答案 0 :(得分:8)

你需要

this->nod.find(k2);

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

基类和派生类是模板,在代码nod中是一个非依赖名称,因此在graph的声明中查找。这是两阶段查找的第一阶段。在这个阶段,编译器(如果遵循标准的名称查找规则)不可能知道nod的意思,因为它在第二阶段之前不考虑基类。因此有必要告诉编译器在第二阶段应该查找nod。为此,我们通过使用上述表单之一明确告诉它nod在基类中。

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

总之,这里有两个问题:

  1. nod不是依赖名称,因此会在第一阶段进行查找。
  2. 声明为nod的基类模板在第二阶段之前不可用,因此无法解析名称。
  3. 通过使用this->nod_base_graph<K, void*, T>::nod,我们明确地处理了一个从属名称,迫使查找在第二阶段进行。

    见第7至10点here

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

答案 1 :(得分:3)

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

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