在 C++ 中使所有派生模板 class 成为其他 class 的朋友
Make all derived template classes friend of other class in C++
假设我必须遵循以下层次结构:
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 */
}
};
现在我想要一个独立的 Class(不是派生自 Base),它可以直接从 Base 或任何 Derived class 访问 Base<T>::container
。我读到了 template friend classes 这似乎是我的问题的解决方案,但我无法弄清楚语法然而。
我正在寻找类似的东西:
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()
friend class行导致error: specialization of ‘template<class T> class Base’ must appear at namespace scope template<T> friend class Base<T>
并且成员变量container
是仍然无法访问。
几个问题:
就像你在定义 class 模板时没有在 class 名称后面加上 <T>
一样:
template <class T> class X<T> { ... }; // WRONG
template <class T> class X { ... }; // RIGHT
在声明 class 模板时,您不应该将它放在 class 名称之后,无论是在前向声明还是友元声明中:
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
(除非您正在创建 class 模板偏特化。例如,如果 class 模板 X
已经声明,则 template <class T> class X<T*> { ... };
定义偏特化当模板参数是指针时,将使用它代替主模板。)
并且你的好友声明是倒过来的:它需要出现在 class 中,其中包含非 public 成员,并将另一个命名为 class(es)允许使用成员。 (如果反过来,那么任何新 class 都可以访问任何其他 class 的私有和受保护成员,而无需拥有 class 的许可!)
所以你需要:
template <class T> class Foo;
template<class T> class Base {
template <class U> friend class Foo;
protected:
T container;
};
有时不需要 Foo
的前向声明,但我认为它使事情变得更清晰,并且当事情开始变得越来越复杂时,它可以避免陷阱,例如命名空间、嵌套 classes 等.
只有Base
可以说Foo
是它的朋友。
template<typename T> friend class Foo; // every Foo<T> is a friend of Base
假设我必须遵循以下层次结构:
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 */
}
};
现在我想要一个独立的 Class(不是派生自 Base),它可以直接从 Base 或任何 Derived class 访问 Base<T>::container
。我读到了 template friend classes 这似乎是我的问题的解决方案,但我无法弄清楚语法然而。
我正在寻找类似的东西:
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()
friend class行导致error: specialization of ‘template<class T> class Base’ must appear at namespace scope template<T> friend class Base<T>
并且成员变量container
是仍然无法访问。
几个问题:
就像你在定义 class 模板时没有在 class 名称后面加上 <T>
一样:
template <class T> class X<T> { ... }; // WRONG
template <class T> class X { ... }; // RIGHT
在声明 class 模板时,您不应该将它放在 class 名称之后,无论是在前向声明还是友元声明中:
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
(除非您正在创建 class 模板偏特化。例如,如果 class 模板 X
已经声明,则 template <class T> class X<T*> { ... };
定义偏特化当模板参数是指针时,将使用它代替主模板。)
并且你的好友声明是倒过来的:它需要出现在 class 中,其中包含非 public 成员,并将另一个命名为 class(es)允许使用成员。 (如果反过来,那么任何新 class 都可以访问任何其他 class 的私有和受保护成员,而无需拥有 class 的许可!)
所以你需要:
template <class T> class Foo;
template<class T> class Base {
template <class U> friend class Foo;
protected:
T container;
};
有时不需要 Foo
的前向声明,但我认为它使事情变得更清晰,并且当事情开始变得越来越复杂时,它可以避免陷阱,例如命名空间、嵌套 classes 等.
只有Base
可以说Foo
是它的朋友。
template<typename T> friend class Foo; // every Foo<T> is a friend of Base