问题描述
示例:
template<class T>
class Base {
public:
Base();
friend class T;
};
现在这不起作用...有没有办法做到这一点?
Now this doesn't work... Is there a way of doing this?
我实际上正在尝试制作一个像这样的通用类密封器:
I'm actually trying to make a general class sealer like this:
class ClassSealer {
private:
friend class Sealed;
ClassSealer() {}
};
class Sealed : private virtual ClassSealer
{
// ...
};
class FailsToDerive : public Sealed
{
// Cannot be instantiated
};
我在这个网站的某个地方找到了这个例子,但我找不到它......(这里)
I found this example on this site somewhere but I can't find it... (here)
我知道有其他方法可以做到这一点,但刚才我很好奇你是否真的可以做这样的事情.
I know there are other ways of doing this but just now I'm curious if you actually can do something like this.
推荐答案
它在标准中被明确禁止,即使某些版本的 VisualStudio 允许它.
It is explicitly disallowed in the standard, even if some versions of VisualStudio do allow it.
C++ 标准 7.1.5.3 详细类型说明符,第 2 段
C++ Standard 7.1.5.3 Elaborated type specifiers, paragraph 2
3.4.4 描述了如何在一个标识符中进行名称查找.详细类型说明符.如果标识符解析为一个类名或枚举名,详细类型说明符引入它进入声明相同简单类型说明符引入的方式它的类型名称.如果标识符解析到 typedef 名称或模板类型参数,详细类型说明符是畸形.[注意:这意味着,在一个类模板中模板类型参数 T,声明朋友类T;是畸形.]
3.4.4 describes how name lookup proceeds for the identifier in an elaborated-type-specifier. If the identifier resolves to a class-name or enum-name, the elaborated-type-specifier introduces it into the declaration the same way a simple-type-specifier introduces its type-name. If the identifier resolves to a typedef-name or a template type-parameter, the elaborated-type-specifier is ill-formed. [Note: this implies that, within a class template with a template type-parameter T, the declaration friend class T; is ill-formed. ]
我认为上面的代码是一种密封(禁止扩展)类的模式.还有另一种解决方案,它不会真正阻止扩展,但会标记无意中从类中扩展.正如在 ADOBE 源库中所见:
I recognize the code above as a pattern to seal (disallow the extension of) a class. There is another solution, that does not really block the extension but that will flag unadvertidly extending from the class. As seen in 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 )
{//...
};
虽然它允许扩展,如果你真的强迫它:
While it allows extension if you really force it:
class SealBreaker : public Sealed, ADOBE_FINAL( Sealed )
{
public:
SealBreaker() : adobe::implementation::final<Sealed>(), Sealed() {}
};
它会限制用户误操作.
编辑:
即将到来的 C++11 标准确实允许您与语法略有不同的类型参数成为朋友:
The upcoming C++11 standard does allow you to befriend a type argument with a slightly different syntax:
template <typename T>
class A {
// friend class T; // still incorrect: elaborate type specifier
friend T; // correct: simple specifier, note lack of "class"
};
这篇关于让模板参数成为朋友?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持跟版网!