GCC 在模板继承中不可理解的地方(编译器问题)

如果一个模板类继承自另外一个模板类,则被继承的模板类的成员必须进行限定。

(如果不限定,则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(名字查找)”可以找到更多关于这个问题的信息。最常见的四个名字查找错误如下:

错误

描述

模板类中有依赖关系的名字

在函数模板中的名称可以是有依赖关系的,也可以是没有依赖关系的。有依赖关系的名称在词汇上依赖于模板参数,在模板实例化的时候进行名称查找;而没有依赖关系的名称在模板被解析的时候进行名称查找,该过程发生在模板被实例化之前。

模板中的未限定名称

在模板参数类中的名称必须进行限定,可以显式地说明该名称来自模板(Foo<T>::mArray),也可以使用this指针来指明该名称来自模板的实例。如果您显式地声明某名称来自模板,相应的名称查找会在实例化时进行;否则,如果您使用this指针,则名称查找在模板定义时进行。

模板超类中的未限定名称

在当前模板的模板超类中定义的名称必须限定为来自超类。另外一种方法是在那些名称之前加上this->来进行限定。

被继承的模板类中的未限定名称

如果一个模板类继承自另外一个模板类,则被继承的模板类的成员必须进行限定。请参见列表1中的实例。


列表1中显示一个属于被继承的模板类的未限定名称的例子。

template <typename T> struct Base 
 
{
 
 void f();
 
};
 
 
template <typename T> struct Derived : public Base<T> 
 
{
 
 void g() 
 
 {
 
 f(); // ERROR: Name not found.,这里的提示是问题的关键
 
 this->f(); // OK
 
 Derived::f(); // OK
 
 Base<T>::f(); // OK
 
 }
 
};
 

    Jacky Wu  2006年4月4日       

转载请注明出处:http://blog.csdn.net/imwkj

 

你可能感兴趣的:(C++,struct,gcc,Class,编译器,BT)