这个程序有什么范围问题吗?
#include<iostream>
using namespace std;
template<class Type>
class Base
{
public:
Type member;
Base(Type param): member(param){
}
};
template<class Type>
class Derived: public Base<Type>
{
public:
Derived(Type param):Base<Type>(param){
// ^
// |_______ Not writing Type here gives error, why?
}
void display()
{
cout << member; /** ERROR HERE **/
}
};
int main()
{
Derived<int> p(5);
p.display();
return 0;
}
Run Code Online (Sandbox Code Playgroud)
我收到错误'member' was not declared in this scope.如何解决问题?
sbi*_*sbi 10
你的问题有些令人困惑.起初我以为你base<Type>在成员初始化列表中询问,然后我以为你问的是访问member,然后回到第一个......现在我在想你们两个都问,所以我会回答两个问题.
不写这里的类型给出错误,为什么?
当您使用类模板的名称(my_class_templ)时,它引用的模板不是类型.要将其用作类型,您需要提供模板参数(my_class_templ<int>,my_class_templ<T>).因此,只要需要类型名称(并且包括初始化列表中的基类名称),就需要提供模板参数.
您可以在类模板的定义中省略类模板名称的模板参数列表.例如,可以将复制构造函数声明为
my_class_templ(const my_class_templ& rhs);
Run Code Online (Sandbox Code Playgroud)
代替
my_class_templ<T>(const my_class_templ<T>& rhs);
Run Code Online (Sandbox Code Playgroud)
这只是一个小的语法糖,允许你输入更少.
但是,在类模板定义之外,您需要明确说明所有模板参数.派生类也是如此:
my_dervied_class_templ(const my_derived_class_templ& rhs)
: my_class_templ<T>(rhs) // need to spell out <T> here
{
}
Run Code Online (Sandbox Code Playgroud)
我收到错误
'member' was not declared in this scope.如何解决问题?
当编译器首先遇到模板时,只有它的定义,编译器还没有看到实例化.编译器不知道在实例化时是否可能存在范围内的模板特化.但是,您可以将模板专门用于Base<T>::member引用其他内容或不完全定义.(比方说,专门化Base<void>没有数据成员.)因此,编译器不得推测成员Base.因此,他们不会被抬头看Derived.
结果是,如果你需要引用其中一个成员Base,你需要告诉编译器你希望有一个Base<T>这样的成员.这是通过完全限定其名称来完成的:Base<Type>::member.
不写这里的类型给出错误,为什么?
如果省略Type,则编译器无法确定Base是基类还是其成员Derived.指定Type确保它Base是模板类[基类].
'member'未在此范围内声明
这与名称查找规则(依赖基类)有关.
C++ 03 [第14.6/8节]说
在查找模板定义中使用的名称声明时,通常的查找规则(3.4.1,3.4.2)用于非依赖名称.依赖于模板参数的名称查找被推迟,直到知道实际模板参数(14.6.2).
现在Section 14.6.2/3说
在类模板的定义或类模板的成员中,如果类模板的基类依赖于模板参数,则在类的定义时,在非限定名称查找期间不会检查基类作用域.模板或成员或在类模板或成员的实例化期间.
member 是一个非限定名称,因此不检查基类.
所以你有两个选择.
Memberie的完全限定名称Base<Type>::memberthis->member.