【问题标题】:Member of base class template is out of scope in derived class template with same template argument基类模板的成员在具有相同模板参数的派生类模板中超出范围
【发布时间】:2013-04-04 14:19:37
【问题描述】:

下面的代码给了我一个编译错误'value'没有在这个范围内声明

template<class T>
struct Base {
    int value;
};

template <class T>
struct Derived : public Base<T> {
    int getValue() { return value; }
};

我觉得很奇怪

  • 如果Derived 继承自Base&lt;std::string&gt;,则代码编译,
  • 如果我return Base&lt;T&gt;::value,代码编译。

为什么代码不能按原样编译? Derived&lt;T&gt;::getValue()的范围内没有以什么方式声明'value'?

【问题讨论】:

    标签: c++ templates


    【解决方案1】:

    因为value 是一个非限定名称,并且在名称查找的第一阶段,编译器将不知道这是从基类继承的数据成员(它没有已实例化Base&lt;T&gt;)。因此,它将搜索全局命名空间,并没有找到名为value 的变量;因此,它会发出错误。

    这是解决此问题的典型方法:

    template <class T>
    struct Derived : public Base<T> {
        int getValue() { return this->value; }
        //                      ^^^^^^
    };
    

    显式取消引用this 告诉编译器后面的名称是(可能继承的)数据成员的名称,并且查找应该延迟到成员函数实际实例化的位置。当然,您的解决方案是:

    return Base<T>::value;
    

    同样好,因为它还告诉编译器value 继承自基类Base&lt;T&gt;

    对于从Base&lt;std::string&gt;派生的问题,编译器可以立即查找Base&lt;std::string&gt;是否包含名为value的数据成员(因为它不依赖于任何模板参数),如果是这样,它将能够确定表达式的格式正确。

    但是,如果您的基类是Base&lt;T&gt;,而T 在名称查找的第一阶段是未知的,则编译器无法分辨value 是什么(Base 的特化为不同的T s 甚至可能根本没有value)。

    C++11 标准第 14.6/3 段:

    在类或类模板的定义中,如果基类依赖于模板参数,则基类 在类模板的定义点处,在非限定名称查找期间不检查范围 或成员或在类模板或成员的实例化期间。 [...] [示例

    struct A {
        struct B { / ... / };
        int a;
        int Y;
    };
    
    int a;
    
      template<class T> struct Y : T {
        struct B { / ... / };
        B b; // The B defined in Y
        void f(int i) { a = i; } // ::a
        Y* p; // Y<T>
      };
    
    Y<A> ya;
    

    模板参数A的成员A::BA::aA::Y不影响名称的绑定 Y&lt;A&gt;。 —结束示例 ]

    【讨论】:

    • @Oswald:谢谢,很高兴我能帮上忙
    • 非常好,我可以像往常一样添加:)。
    • 如果我想在子类中使用基类的typedef name怎么办?
    猜你喜欢
    • 2011-05-11
    • 2012-09-12
    • 1970-01-01
    • 1970-01-01
    • 2021-07-25
    • 1970-01-01
    • 2013-02-18
    • 2019-11-09
    • 1970-01-01
    相关资源
    最近更新 更多