模板类使用friend时需要注意的一个问题

来源:互联网 发布:Ubuntu autoremove 编辑:程序博客网 时间:2024/06/05 22:54

 

在使用模版类封装一个B-Tree时我遇到了一个问题,我的模版类定义如下:

//节点类定义

template <class TKey,class TData,UINT TRank>

class CGRSBTreeNode

{

……

public:

     friend class CGRSBTree; //注意这一行,实际不能这样使用的

};

 

//B-Tree类的定义

template <class TKey,class TData,UINT TRank = 10>

class CGRSBTree

{

protected:

     CGRSBTreeNode<TKey,TData,TRank>* m_pRoot; //树根节点

……

};

定义的目的是使的CGRSBTree类能够访问节点类定义的私有或保护乘员,这个要求是很合理的,但是,这会引起一个编号为C3857和C2989的VC编译器(VS2008所带的10.0版本)错误。C2989意思是说,我的friend class CGRSBTree;这句已经说明CGRSBTree是一个非模板类,而我后面有声明他为模版类,编译器不干了,而C3857又认为我的这句实际上已经把CGRSBTree声明为了模版类,后面的声明是一个重复参数的声明,即不需要再声明模版参数了。为什么编译器会得出这么矛盾的错误呢?

在仔细的分析后我才发现,其实friend声明在模版类中不能这样使用,因为CGRSBTree类还没有实例化,它仅是一个没有生成任何实际类的模板而已,此处的friend实际上是一个不明确的声明,即把哪个参数实例化的CGRSBTree类当作友元,编译器不知道,模版类也不知道,我也不知道,因为我也不知道具体会怎么样实例化这两个类,当然也就无法知道具体实例化后的友元关系,这个地方的声明实际是对编译器的误导。难为编译器得出了相互矛盾的结论。

这个问题深刻说明在使用C++模版类时,有些细节的地方不能用封装类的思想来封装,这也深刻的体现了模版类和类的本质区别。

为了使这类问题不在发生,可以理解模版类为一堆类的抽象,不是具体的类,因此象friend这种需要明确类定义的语法就不能用在模版类上了。

原创粉丝点击