从模板化父类访问继承的变量[重复]
Posted
技术标签:
【中文标题】从模板化父类访问继承的变量[重复]【英文标题】:Accessing inherited variable from templated parent class [duplicate] 【发布时间】:2010-10-10 23:14:03 【问题描述】:考虑以下代码:
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 报错
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++ 编译器也接受它。
新的 Gnu C++ 编译器是否遵守标准?如果是这样,那么继承类无法看到受保护的继承成员变量的原因是什么?
如果有的话
int A() return a;
在 Foo 中,我得到错误
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 -fpermissiveâ, G++ will accept your code, but allowing the use of an undeclared name is deprecated)
当我尝试在 Bar 的成员函数中使用它时。 我也觉得这很奇怪:Bar 继承了 Foo,所以我认为 Bar 范围内的 A() 显然是 Foo::A()。
【问题讨论】:
【参考方案1】:GCC 给出的错误信息表明您的 GCC 版本仍然存在仅在 GCC4.7 主干版本中解决的错误。旧版本,包括 GCC4.1 将很乐意接受以下代码
template<typename T>
struct A
void f(int)
;
template<typename T>
struct B : A<T>
void g() T t = 0; f(t);
;
int main()
B<int> b; b.g();
GCC 将在基类A<T>
中的f(t)
中查找f
,并将在基类中找到声明。 GCC 这样做是因为 f
是依赖的,因为 f
的参数“依赖于模板参数”(看看它给你的错误消息!)。但标准禁止 GCC 这样做有两个原因
标准规定,使用非限定名称永远不会在依赖基类中找到声明无论名称是否依赖。
标准规定在实例化时对函数名的依赖查找只会执行 ADL。
GCC 4.7 在这方面正确实施了标准。
【讨论】:
【参考方案2】:后来的 GCC 版本正确地实现了该标准。
该标准规定模板中的非限定名称是不相关的,并且必须在定义模板时进行查找。那时依赖基类的定义是未知的(可能存在基类模板的特化),因此无法解析非限定名称。
对于在基类中声明的变量名和函数名都是如此。
正如您所观察到的,解决方案是提供变量或函数的限定名称,或者提供“使用”声明。例如
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% 确定使用版本的语法是否正确,也无法从这里进行测试,但你明白了)。
【讨论】:
谢谢。我要撸起袖子改代码了。 我相信你必须在类级别做 using 语句,即模板以上是关于从模板化父类访问继承的变量[重复]的主要内容,如果未能解决你的问题,请参考以下文章