在派生类中访问一个类的受保护成员

9

我这里有一个旧的代码库,其中使用了受保护的成员变量。是否使用此方法可以讨论。然而,代码必须能够在gcc3下编译通过。 我有一个派生的模板类Bar,它使用了从类模板Foo继承的受保护成员变量x,如下所示:

template <class Something> class Foo {  
public:  
// stuff...  
protected:  
  some::type x;  
}

template <class Something> Bar : Foo<Something> {
public:
  void cleanup();
}

在cleanup()方法的声明中,对x进行了一些操作。
template <class Something> void Bar<Something>::cleanup() {
  doSomeThingCleanUpLike (x);
}

这在gcc4下不起作用,尽管它应该在gcc3下正常工作。当我将其更改为以下内容时,它可以工作:

doSomeThingCleanUpLike (this->x);

这是为什么呢?

1
“模板类”这个术语常常让人感到困惑。正确的术语应该是“类模板”,因为它是用于类的模板,而不是一个类本身。我可以编辑你的问题,但这也可能是你感到困惑的原因之一。 - MSalters
1
你的函数定义“cleanup”不符合规范。缺少返回类型和“Bar”的模板参数。确定这就是你代码中的写法吗? - Johannes Schaub - litb
谢谢litb。我已经更改了。咖啡因含量不够高,无法发现它。同时更改为“类模板”。 无论是“模板类”还是“类模板”,都不应该影响问题的解决。这个术语只是非正式地被广泛使用。 - GeeF
2个回答

14
在派生类中使用的表达式x,根据标准规则,并不依赖于任何派生类的模板参数。因此,在模板定义的上下文中进行查找,而不是在使用/实例化的时候。尽管模板基类似乎可见,但由于它是一个模板类,可能会涉及特定的模板实例化,因此基类模板定义无法用于名称查找。
通过将表达式更改为this->x,您正在使其成为依赖表达式(类模板中的this始终取决于模板参数)。这意味着查找将在实例化上下文中发生,此时基类已完全知道并且其成员可见。

在编程中,使用正确的术语:“依赖名称”/“非依赖名称”,加1分。 - David Rodríguez - dribeas

6

当您定义派生模板时,编译器只知道基础模板类的名称,但不知道其细节,因此编译器不知道派生类具有继承成员。为了告诉编译器成员的存在,使用 this->,就像您所做的一样。

实际上,这是这个问题的重复。


1
需要注意的是,添加 this-> 不是一种惯例,而是将非依赖名称转换为依赖名称的一种方式。请参见 Charles 的答案。 - David Rodríguez - dribeas
很好,这个问题以前的标题确实不好。现在已经修正了。 - MSalters

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接