template class Tclass baseclass{protected: T data;public: baseclass(){}; void setData(T d);};templateclass Tvoid baseclassT::setT(T d){ data = d;} 上面显示的是我的基类,一个受保护的成员变量,一个setter. template class Tc
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的菜鸟,我敢肯定我错过了一些明显的东西.
这不起作用的原因是C模板命名解析方式的怪癖.特别是,如果你有一个继承自另一个依赖于模板类型的类的模板类(正如你在这种情况下所做的那样),你不能直接访问该基类的成员而不给编译器一个提示看.这是你得到的错误的原因.要解决此问题,您可以将构造函数重写为
template<class T> aclass<T>::aclass(T d){ setData(d); this->data = d; }
现在编译器知道数据必须以某种方式成为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; };
喜欢这个 – >对于数据成员来说,这个技巧使得名称setData的来源明确无误,并帮助编译器知道你在说什么.
希望这可以帮助!