2012-01-23 40 views
50

比方说,我创建一个类二叉树,BT,和我有一个类,它描述了树,BE的元素,像带模板班朋友的班级模板,这里究竟发生了什么?

template<class T> class BE { 
    T *data; 
    BE *l, *r; 
public: 
... 
    template<class U> friend class BT; 
}; 

template<class T> class BT { 
    BE<T> *root; 
public: 
... 
private: 
... 
}; 

这似乎工作;不过,我对下面发生的事情有疑问。

我最初试图申报的朋友,因为

template<class T> friend class BT; 

但它似乎有必要使用U(或大于T其他东西)在这里,这是为什么?这是否意味着任何特定的BT对任何特定的BE类都是朋友?

模板和朋友的IBM页面上有不同类型的函数但不包括类的朋友关系的示例(并且猜测语法尚未融合到解决方案中)。我希望了解如何获得我希望定义的朋友关系类型的规范。

回答

76
template<class T> class BE{ 
    template<class T> friend class BT; 
}; 

不允许,因为模板参数不能互相影响。嵌套模板必须具有不同的模板参数名称。


template<typename T> 
struct foo { 
    template<typename U> 
    friend class bar; 
}; 

这意味着barfoo的朋友,无论bar的模板参数。 bar<char>,bar<int>,bar<float>和其他bar将是foo<char>的朋友。


template<typename T> 
struct foo { 
    friend class bar<T>; 
}; 

这意味着barfoo朋友时bar的模板参数匹配foo的。只有bar<char>将是foo<char>的朋友。


在你的情况下,friend class bar<T>;应该是足够的。

+2

这种结构在我的代码 友元类BT 抛出一个错误的朋友线 错误:“BT”不是一个模板 即使它后来被宣布为 模板类BT { ... } –

+1

所以秘密是我需要转发申报BT以便使用朋友类BT ;行中的BE,但不适用于模板的朋友类BT ;.谢谢您的帮助! –

+16

更具体地说:你必须转发声明'模板 BT类;'_before_ BE的定义,然后使用'朋友类BT ;'_side_类BE。 –

-1

在我的情况下,该解决方案正常工作:

template <typename T> 
class DerivedClass1 : public BaseClass1 { 
    template<class T> friend class DerivedClass2; 
private: 
int a; 
}; 

template <typename T> 
class DerivedClass2 : public BaseClass1 { 
    void method() { this->i;} 
}; 

我希望这将是有益的。

+5

当您为模板参数创建阴影时,该解决方案应该如何正确工作,否则不会将DerivedClass2的朋友访问权限用于DerivedClass1以供使用? – kornman00

1

为了笼络另一个同类型的结构:

template<typename T> 
struct Foo 
{ 
    template<typename> friend struct Foo; 
}; 

注意,在template<typename> friend struct Foo;你不应该写Ttypename/class;否则会导致模板parm shadowing错误。

+3

请改善您的答案。 – swiftBoy

1

这是没有必要的,所以你如果得到故障点更少命名参数重构:

 template <typename _KeyT, typename _ValueT> class hash_map_iterator{ 
     template <typename, typename, int> friend class hash_map; 
     ...