template <class T>
class baseclass{
protected:
T data;
public:
baseclass(){};
void setData(T d);
};
template<class T>
void baseclass<T>::setT(T d){
data = d;
}
上面显示的是我的基类,一个受保护的成员变量,一个setter。
template <class T>
class aclass : public baseclass<T>
{
public:
aclass(T d);
};
template<class T>
aclass<T>::aclass(T d){
setData(d); <---WORKS
data = d; <---DOESN'T WORK
}
现在这是我的第一个子类。出于某种原因,直接访问受保护的成员变量是不行的,虽然我认为它应该。但是,访问setter工作正常。我是C ++的菜鸟,我敢肯定我错过了一些明显的东西。
答案 0 :(得分:8)
这不起作用的原因是C ++模板命名解析方式的怪癖。特别是,如果你有一个继承自另一个依赖于模板类型的类的模板类(正如你在这种情况下所做的那样),你不能直接访问该基类的成员而不给编译器一个提示看。这是你得到错误的原因。
要解决此问题,您可以将构造函数重写为
template<class T>
aclass<T>::aclass(T d){
setData(d);
this->data = d;
}
现在编译器知道data
必须以某种方式成为aclass<T>
的成员,它可以找到它正在寻找的内容。
有趣的是,出于同样的原因,你也应该在前一行收到错误。我不确定为什么决定编译。要解决此问题,您可以执行以下操作:
template<class T>
aclass<T>::aclass(T d){
this->setData(d);
this->data = d;
}
或者,您可以添加using
声明来告诉编译器aclass
从其父类继承setData
方法。在类声明中,考虑添加以下行:
template <class T>
class aclass : public baseclass<T>
{
public:
aclass(T d);
using baseclass<T>::setData;
};
与数据成员的this->
一样,这个技巧使得名称setData
的来源明确无误,并帮助编译器知道你在说什么。
希望这有帮助!