Jest to wyraźnie zabronione w standardzie, nawet jeśli niektóre wersje VisualStudio na to zezwalają.
C++ standardowe 7.1.5.3 Opracowano Specyfikatory typu, akapit 2
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. ]
uznaję, powyższy kod jako wzorzec do uszczelniania (uniemożliwić rozszerzenie) klasy. Istnieje inne rozwiązanie, które tak naprawdę nie blokuje rozszerzenia, ale które będzie oznaczało nieodwracalne rozszerzenie klasy. Jak widać na ADOBE Source Library:
namespace adobe { namespace implementation {
template <class T>
class final
{
protected:
final() {}
};
}}
#define ADOBE_FINAL(X) private virtual adobe::implementation::final<T>
z wykorzystania:
class Sealed : ADOBE_FINAL(Sealed)
{//...
};
Chociaż umożliwia rozszerzenie jeśli naprawdę zmusić go:
class SealBreaker : public Sealed, ADOBE_FINAL(Sealed)
{
public:
SealBreaker() : adobe::implementation::final<Sealed>(), Sealed() {}
};
To będzie ograniczać użytkowników z błędnie zrobić.
EDIT:
nadchodzący standard C++ 11 nie pozwala na to rodzaj argumentu zaprzyjaźnić z nieco innej składni:
template <typename T>
class A {
// friend class T; // still incorrect: elaborate type specifier
friend T; // correct: simple specifier, note lack of "class"
};
... znowu, C++ 11 zezwala na słowo kluczowe "final", na przykład: klasa X final {...} (lub możesz sprawić, że poszczególne funkcje wirtualne staną się ostateczne). W każdym przypadku próbowałem powyższego kodu ("przyjaciel T;") z g ++ 4.8.4 _without_ the -std = C++ 11 flag i kompiluje się dobrze. –