使用模板和继承时出现未声明的标识符问题的跟进

5
我遇到了与此前的问题相同,链接如下: Use of undeclared identifier in C++ with templates and inheritance 总结一下,我们试图从子类中访问模板类的保护属性。应该使用this->attribute而不是仅使用attribute。然而,我想知道为什么在Visual Studio 2012中不需要添加this->,程序可以正确编译和执行。我也想知道是否有办法在OS X上的gcc或其他编译器中实现这个功能。
编辑: 下面是我用于在Visual Studio 2012中测试的代码。
//file a.h

template<class T>
class a
{
public:
    a(){value = 2;};
protected:
    T value;
};

template<class T>
class b: public a<T>
{
public:
    T getValue(){return value;};
};

//file main.cpp
#include <iostream>
#include "a.h"
using namespace std;
int main()
{
    b<int> myTest;
    cout<<myTest.getValue();
    system("pause");
    return 0;
}

使用g++编译会失败,但使用Visual Studio 2012可以成功编译。

哦,这在VS2012中还没有修复吗? - Chubsdad
你能展示一下你的代码吗?什么是属性? - Chubsdad
我已经编辑了我的原始问题,添加了我在 Visual Studio 中使用但不应该工作的代码。 - Sam
1个回答

4
我认为适用于这种情况的标准部分是§14.6.2/3,该部分规定如下:

在类模板或类模板成员的定义中,如果类模板的基类依赖于一个模板参数,则在未限定名称查找时,不会在类模板或成员的定义点或类模板或成员实例化期间检查基类作用域。

由于您的基类依赖于模板参数,因此不应检查相关的基类范围。然而,一些编译器处理这个有误。例如,GCC进行了额外的相关基类范围查找,这在版本4.7中得到了修复(Bug# 24163, 29131)。我不知道Visual Studio编译器为什么允许这样做。但如果它确实这样做,则在这方面显然不符合标准。您不应该依赖于该错误,并且绝对不应该寻找具有类似错误的编译器来依赖。


这非常有趣。也许微软(这只是我的猜测)没有为了易用性而纠正那个问题? - Sam
@Sam:我不知道他们为什么不纠正它。然而,易用性是一回事,做程序员期望的事情是另一回事。一个人可以使用相同名称引用参数,并假设编译器从全局范围内获取它,而微软将以其易用性非标准行为惊喜开发人员。微软实际上有一个长期惊喜开发人员的C++编译器记录...我多年来没有使用过他们的产品,但我认为在版本6中,他们曾经在循环范围内仅调用对象的构造函数一次。 - user405725
在循环范围内,您的意思是例如使用多个构造函数的while循环,并且它只会调用构造函数一次吗? - Sam
@Sam:没错。但那是很久很久以前的事了,就像是我的另一个生命。另一方面,所有的编译器都有bug :) - user405725
我正在为这个问题苦恼。我已经有一段时间没有用C++编程了,而且我忘记了这个可爱的棘手小角落。这种语言确实不友好。 - Eloff

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