从模板化父类访问继承的变量[重复]

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&lt;T&gt; 中的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 语句,即模板 Bar : public Foo using Foo::a; ... ;

以上是关于从模板化父类访问继承的变量[重复]的主要内容,如果未能解决你的问题,请参考以下文章

PHP - 子类没有从父类继承[重复]

Django 第六课 模板继承

子类从父类继承过来的方法可以操作子类自己定义的成员变量吗

自动初始化父类和子类中的成员变量[重复]

java中成员变量代码块构造函数运行顺序

[短文速读-3] 实例化子类会实例化父类么