假设我必须遵循以下层次结构:
template<class T> class Base {
protected:
T container;
};
template<class T> class Derived1 : public Base<T> {
public:
void f1() {
/* Does stuff with Base<T>::container */
}
};
template<class T> class Derived2 : public Base<T> {
public:
void f2() {
/* Does stuff with Base<T>::container */
}
};
现在,我需要一个独立的类(不是从Base派生的),该类可以直接从Base或任何派生类访问Base<T>::container
。我读到有关 模板朋友类 的信息,这似乎是解决我的问题的方法,但我仍无法弄清楚语法。
我正在寻找类似的东西:
template<class T> class Foo{
template<T> friend class Base<T>; // <-- this does not work
public:
size_t bar(const Base<T> &b) const{
return b.container.size();
}
};
Derived1<std::vector<int> > d;
d.f1();
Foo<std::vector<int> > foo;
size_t s = foo.bar()
朋友班级 导致error: specialization of ‘template<class T> class Base’ must appear at namespace scope template<T> friend class Base<T>
,而成员变量container
仍然不可访问。
答案 0 :(得分:1)
几个问题:
就像在定义类模板时不要在类名后放置<T>
一样:
template <class T> class X<T> { ... }; // WRONG
template <class T> class X { ... }; // RIGHT
在声明类模板时,无论是在前向声明还是在朋友声明中,都不应该将其放在类名之后:
template <class T> class X<T>; // WRONG
template <class T> class X; // RIGHT - declares the template exists
template <class T> friend class X<T>; // WRONG
template <class T> friend class X; // RIGHT - says all specializations of X are friends
(除非您要创建类模板的部分专业化。例如,如果已经声明了类模板X
,则template <class T> class X<T*> { ... };
定义了部分专业化,在使用时将代替主模板模板参数是一个指针。)
您的朋友声明倒退了:它需要与非公共成员一起出现在类中,并命名允许使用这些成员的其他类。 (如果它以其他方式起作用,那么任何新类都可以在未经拥有类许可的情况下访问其他任何类的私有成员和受保护成员!)
所以您需要:
template <class T> class Foo;
template<class T> class Base {
template <class U> friend class Foo;
protected:
T container;
};
有时不需要Foo
的前向声明,但我认为它使事情变得更清楚,当名称空间,嵌套类等开始变得更加复杂时,它可以避免麻烦。
答案 1 :(得分:0)
只有Base
可以说Foo
是它的朋友。
template<typename T> friend class Foo; // every Foo<T> is a friend of Base