从模板化父类访问继承的变量
考虑以下代码:
template<class T> class Foo
{
public:
Foo() { a = 1; }
protected:
int a;
};
template<class T> class Bar : public Foo<T>
{
public:
Bar() { b = 4; };
int Perna(int u);
protected:
int b;
};
template<class T> int Bar<T>::Perna(int u)
{
int c = Foo<T>::a * 4; // This works
return (a + b) * u; // This doesn't
}
g++ 3.4.6、4.3.2 和 4.1.2 给出错误
g++ 3.4.6, 4.3.2 and 4.1.2 give error
test.cpp: In member function `int Bar<T>::Perna(int)':
test.cpp:25: error: `a' was not declared in this scope
g++ 2.96 和 MSVC 6、7、7.1、8 和 9 接受它,(至少)旧的 Intel 和 SGI c++ 编译器也是如此.
g++ 2.96 and MSVC 6, 7, 7.1, 8 and 9 accept it, as do (at least) older Intel and SGI c++ compilers.
新的 Gnu C++ 编译器是否符合标准?如果是,那么继承类无法看到受保护的继承成员变量的原因是什么?
Do the new Gnu C++ compiler obey the standard or not? If they do, what is the rationale behind that inheriting class is not able to see a protected inherited member variable?
另外,如果有
int A() { return a; }
在 Foo 中,我收到错误
in Foo, I get error
test.cpp:25: error: there are no arguments to A that depend on a template parameter, so a declaration of A must be available
test.cpp:25: error: (if you use -fpermissivea, G++ will accept your code, but allowing the use of an undeclared name is deprecated)
当我尝试在 Bar 的成员函数中使用它时.我也觉得很好奇:Bar 继承了 Foo,所以我认为 Bar 范围内的 A() 显然是 Foo::A().
when I try to use it in a member function of Bar. I find that curious as well: Bar inherits Foo, so I think it's obvious that A() in scope of Bar is Foo::A().
推荐答案
后来的 GCC 版本正确实现了标准.
The later GCC versions correctly implement the standard.
该标准规定模板中的非限定名称是非依赖的,必须在定义模板时进行查找.依赖基类的定义当时未知(可能存在基类模板的特化),因此无法解析非限定名称.
The standard specifies that unqualified names in a template are non-dependent and must be looked up when the template is defined. The definition of a dependent base class is unknown at that time (specializations of the base class template may exist) so unqualified names are unable to be resolved.
对于在基类中声明的变量名和函数名都是如此.
This is true for both variable and function names declared in the base class.
正如您所观察到的,解决方案是提供变量或函数的限定名称,或提供使用"声明.例如
As you have observed the solution is to provide the qualified name of the variable or function, or to provide a "using" declaration. E.g.
template<class T>
int Bar<T>::Perna(int u)
{
int c = Foo<T>::a * 4; // This works
c = this->a * 4; // and this
using Foo<T>::a;
c = a * 4; // and with 'using', so should this
}
(我实际上并不是 100% 确定使用版本的正确语法,也无法从这里进行测试,但您明白了.
(I'm actually not 100% sure about the correct syntax for the using version and can't test from here, but you get the idea).
相关文章