以下代码为我提供了编译错误'value'未在此范围内声明
The following code gives me a compilation error 'value' was not declared in this scope.
template<class T> struct Base { int value; }; template <class T> struct Derived : public Base<T> { int getValue() { return value; } };我觉得非常奇怪,
- 如果派生继承自 Base< std :: string> / li>
- 如果我返回Base< T> :: value ,则代码将编译。
- if Derived inherits from Base<std::string>, the code compiles,
- if I return Base<T>::value, the code compiles.
为什么代码不编译?在 Derived< T> :: getValue()?
Why doesn't the code compile as it is? In what way is 'value' not declared in the scope of Derived<T>::getValue()?
推荐答案因为 value 是一个非限定名称,在名称查找的第一阶段,没有提示这是从基类继承的数据成员(它尚未实例化 Base< T> )。因此,它将搜索全局命名空间,并找不到名为 value 的变量;
Because value is an unqualified name, and during the first phase of name lookup, the compiler will have no clue that this is a data member inherited from a base class (it hasn't instantiated Base<T> yet). Thus, it will search the global namespace, and find no variable called value; consequently, it will emit an error.
这是一个典型的方法来解决这个问题:
Here is a typical approach to solve this problem:
template <class T> struct Derived : public Base<T> { int getValue() { return this->value; } // ^^^^^^ };显式解引用这个告诉编译器下面的名称是(可能是继承的)数据成员的名称,并且查找应该被延迟到成员函数实际被实例化的点。当然,你的解决方案是:
Explictly dereferencing this tells the compiler that the name that follows is the name of a (possibly inherited) data member, and the lookup should be delayed to the point where the member function is actually instantiated. Of course, your solution of doing:
return Base<T>::value;同样好,因为它也告诉编译器 value 从基类 Base 继承。
Is equally good, because it also tells the compiler that value is inherited from the base class Base<T>.
对于从 Base< std :: string> 派生的关注,编译器可以立即查找是否 Base< std :: string> 包含名为 value 的数据成员(因为它不依赖于任何模板参数)
For what concerns deriving from Base<std::string>, the compiler can immediately go and look up whether Base<std::string> contains a data member named value (because it does not depend on any template parameter) and if that is the case, it will be able to determine that the expression is well-formed.
但是,如果你的基类是 Base< ; T> ,其中 T 在名称查找的第一阶段未知,编译器不能告诉什么 是 Base 对于不同的 T 的专业化甚至可能没有 value )。
However, if your base class is Base<T>, where T is unknown during the first phase of name lookup, the compiler can't tell what value is (specializations of Base for different Ts may even not have value at all).
C ++ 11标准的第14.6 / 3段:
Paragraph 14.6/3 of the C++11 Standard:
类或类模板的定义,如果基类依赖于模板参数,则在类模板的定义点处的非限定名称查找期间不检查基类 scope,成员或在类模板或成员的实例化期间。 [...] [示例: 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 :: B code> A :: a 和 A :: Y 模板参数 A 不影响 Y< A> 中的名称的绑定。 - end example ]
The members A::B, A::a, and A::Y of the template argument A do not affect the binding of names in Y<A>. —end example ]
更多推荐
基类模板的成员超出具有相同模板参数的派生类模板的范围
发布评论