示例:
template<class T>
class Base {
public:
Base();
friend class T;
};
现在这不起作用......有没有办法做到这一点?
我实际上正在尝试制作这样的通用类封口机:
class ClassSealer {
private:
friend class Sealed;
ClassSealer() {}
};
class Sealed : private virtual ClassSealer
{
// ...
};
class FailsToDerive : public Sealed
{
// Cannot be instantiated
};
我在这个网站上找到了这个例子,但我找不到它......(here)
我知道有other ways这样做但刚才我很好奇你是否真的可以这样做。
答案 0 :(得分:39)
标准中明确禁止使用它,即使某些版本的VisualStudio允许它。
C ++标准7.1.5.3详细说明的类型说明符,第2段
3.4.4描述了如何对标识符进行名称查找 阐述了式说明符。如果 标识符解析为 一个类名或枚举名, 精心设计的说明者介绍 它进入宣言同样如此 简单类型说明符引入的方式 它的类型名称。如果标识符解析 到typedef-name或 模板类型参数, 精心设计的说明符是 病态的。 [注意:这意味着, 在带有的一个类模板中 模板类型参数T, 声明朋友类T ;是 病态的。 ]
我认为上面的代码是一个密封(禁止扩展)类的模式。还有另一个解决方案,它不会真正阻止扩展,但会标记从类中不加扩展。如ADOBE Source Library中所示:
namespace adobe { namespace implementation {
template <class T>
class final
{
protected:
final() {}
};
}}
#define ADOBE_FINAL( X ) private virtual adobe::implementation::final<T>
用法:
class Sealed : ADOBE_FINAL( Sealed )
{//...
};
如果你真的强迫它,它允许扩展:
class SealBreaker : public Sealed, ADOBE_FINAL( Sealed )
{
public:
SealBreaker() : adobe::implementation::final<Sealed>(), Sealed() {}
};
它会限制用户误做。
编辑:
即将推出的C ++ 11标准允许您使用稍微不同的语法与类型参数建立联系:
template <typename T>
class A {
// friend class T; // still incorrect: elaborate type specifier
friend T; // correct: simple specifier, note lack of "class"
};
答案 1 :(得分:20)
我发现了一个简单的技巧,可以将模板参数声明为朋友:
template < typename T>
struct type_wrapper
{
typedef T type;
};
template < typename T> class foo
{
friend class type_wrapper < T>::type
}; // type_wrapper< T>::type == T
但是我不知道这有助于定义类封口机的替代版本。
答案 2 :(得分:3)
你真的需要这样做吗? 如果您想阻止某人从您的类派生,只需添加注释并使析构函数非虚拟。