模版类继承需显示声明子类成员

作者:, 发表于

在gcc中,存在继承关系的模版类,子类无法直接访问父类的成员,即使该成员是protectedpublic

1.一个简单的例子

#include <iostream> 

template <class  T>
class Base {
public:
    T x;
    Base(T _x) : x(_x) {}
};

template <class T>
class Derived : public Base<T> {
public: 
    Derived(T x) : Base<T>(x) {}
    void log() { 
        std::cout << x << std::endl; 
    }
};

int main()
{
    Derived<int> d(2);
    d.log();
}

gcc编译下会报错:

 In member function 'void Derived<T>::log()':
 16:22: error: 'x' was not declared in this scope

而且这个错误只会在gcc下出现,vc不会出现该问题。因此,编写跨平台的模版库时,应当去gcc下编译。

另外,这个错误只有在DerivedBase都是模版类时才会出现,这两者任何一个不是模版类,都不会出现编译错误。

2.原因

原因据说是因为stdandard 14.6/8

When looking for the declaration of a name used in a template definition, the usual lookup rules (3.4.1, 3.4.2) are used for nondependent names. The lookup of names dependent on the template parameters is postponed until the actual template argument is known (14.6.2).

stdandard 16.2是这么说的:

In the definition of a class template or a member of a class template, if a base class of the class template depends on a template-parameter, the base class scope is not examined during unqualified name lookup either at the point of definition of the class template or member or during an instantiation of the class template or member.

也就是说gcc的编译报错行为符合c++标准。

3.解决方案

3.1.通过子类引用

void log() {
    std::cout << Base<T>::x << std::endl; 
}

3.2.通过this引用

void log() {
    std::cout << this->x << std::endl;
}

3.3.通过using将变量引入子类

using Base<T>::x;
void log() {
    std::cout << x << std::endl;
}

Q.E.D.


上一篇:C++的浮点数取整2016年3月5日
C++的浮点数转整数有四种方法,直接类型转换、round、floor、ceil。其效果如下表: x -1.9 -1.5 -1.1 1.1 1.5 1.9 static_cast<int>(x) -1 -1 -1 1

下一篇:VS2013不支持无文件头的UTF8编码格式2016年6月1日
最近老遇到一个奇怪的问题。在VS 2013编译时,爆出很多警告: warning C4819: The file contains a character that cannot be represented in the current code page (936). Save th


  • 支持使用微薄、微信和QQ的账户登陆进行评论。由各自网站直接认证,不会泄露你的密码。
  • 登陆后可选择分享评论到所绑定的社交网络,如微薄、人人和QQ空间。
  • 评论提交后无法修改。如需修改,请删除原评论再重新提交。
  • 评论支持LaTeX代码,行内公式请用\(a+b=c\),行间公式请用\[a+b=c\]。公式只支持英文字符。