如果一个模板类继承自另外一个模板类,则被继承的模板类的成员必须进行限定。 (如果不限定,则GCC3.4会出现“未定义变量错误”,用VC7编译没有问题) 下面的代码是一个迭代器 TreeIterator 是基类,PostOrderIter 是子类 |
template <class Type> class TreeIterator { public: TreeIterator( const BinaryTree<Type>& BTree) : T(BTree), current(NULL) {} virtual ~TreeIterator() {} virtual void First() = 0; //置第一个位置为当前位置 virtual void operator++() = 0; //当前位置进一 bool operator+() const { return current != NULL; } //判断是否是树中的有效位置 const Type& operator() () const; //返回当前位置所指的值 protected: BinaryTree<Type> T; const BinTreeNode<Type>* current;
private: TreeIterator( const TreeIterator&) {} //拷贝构造 TreeIterator& operator=( const TreeIterator &) const; //赋值 };
//后序游标类 template <class Type> class PostOrderIter : public TreeIterator<Type> { using TreeIterator<Type>::T; using TreeIterator<Type>::current; //在GCC中,需要把这这两个基类变量进行限定,否则无法通过编译(似乎是没有道理的事情,难道是C++的标准发生了变化?) //C++标准中好像没有这种做法,相关的书籍中也没有提到要这样做
public: PostOrderIter( const BinaryTree<Type>& BT ); ~PostOrderIter() {} void First(); //定位到后序次序的第一个结点 void operator++(); //定位到后序次序的下一个结点
protected: Stack< StkNode<Type> > st; //遍历的递归工作栈 };
template <class Type> PostOrderIter<Type>::PostOrderIter( const BinaryTree<Type>& BT ) : TreeIterator<Type> (BT) { st.Push( StkNode<Type> (T.GetRoot()) ); //在此函数中,必须用TreeIterator<Type>::T限定,才可以正确引用 T
|
经过查找GCC编译器的特性,才发现它在处理模板编程中的一些做法。
看过下面的资料,就可以了解为什么会出现这样的问题,
C++模板的变化
C++程序员最常碰到的问题和编译器为遵循C++标准而进行的改变有关系。GCC 3.4开始对错误的C++使用模式进行警告。在现在的GCC 4.0中,那些警告变成了错误。
您可能碰到的一个比较常见的错误是名字查找问题,在形式上表现为“在当前的作用域上没有定义”。在GCC 4.0的文档中检索“name lookup(名字查找)”可以找到更多关于这个问题的信息。最常见的四个名字查找错误如下:
错误 | 描述 |
---|---|
模板类中有依赖关系的名字 | 在函数模板中的名称可以是有依赖关系的,也可以是没有依赖关系的。有依赖关系的名称在词汇上依赖于模板参数,在模板实例化的时候进行名称查找;而没有依赖关系的名称在模板被解析的时候进行名称查找,该过程发生在模板被实例化之前。 |
模板中的未限定名称 | 在模板参数类中的名称必须进行限定,可以显式地说明该名称来自模板( |
模板超类中的未限定名称 | 在当前模板的模板超类中定义的名称必须限定为来自超类。另外一种方法是在那些名称之前加上 |
被继承的模板类中的未限定名称 | 如果一个模板类继承自另外一个模板类,则被继承的模板类的成员必须进行限定。请参见列表1中的实例。 |
列表1中显示一个属于被继承的模板类的未限定名称的例子。
|
Jacky Wu 2006年4月4日
转载请注明出处:http://blog.youkuaiyun.com/imwkj