Uczynienie parametru szablonu przyjacielem?
Przykład:
template<class T>
class Base {
public:
Base();
friend class T;
};
Teraz to nie działa... Jest na to jakiś sposób?
[[2]} właśnie staram się zrobić taki sealer klasy ogólnej:
class ClassSealer {
private:
friend class Sealed;
ClassSealer() {}
};
class Sealed : private virtual ClassSealer
{
// ...
};
class FailsToDerive : public Sealed
{
// Cannot be instantiated
};
Znalazłem ten przykład na tej stronie gdzieś, ale nie mogę go znaleźć... ( tutaj )
Wiem, że istnieją inne sposoby na zrobienie tego, ale teraz jestem ciekawa, czy naprawdę możesz zrobić coś takiego.
3 answers
Jest to wyraźnie zabronione w standardzie, nawet jeśli niektóre wersje VisualStudio na to zezwalają.
C++ Standard 7.1.5.3, paragraf 2
3.4.4 opisuje przebieg wyszukiwania nazwy dla identyfikatora w opracowano na podstawie materiału źródłowego. Jeśli identifier resolves to a class-name or enum-name, opracowany-Typ-specifier wprowadza to w deklaracji to samo sposób prosty-typ-specifier wprowadza jego nazwa typu. Jeśli identifier resolves do typedef-name Lub a typ szablonu-parametr, opracowano na podstawie materiału źródłowego. źle ukształtowany. [Uwaga: oznacza to, że, w szablonie klasy z typ szablonu-parametr T, declaration friend class T ; is źle ukształtowany. ]
Uznaję powyższy kod jako wzorzec do zapieczętowania (zablokowania rozszerzenia) klasy. Jest jeszcze jedno rozwiązanie, które tak naprawdę nie blokuje rozszerzenia, ale będzie oznaczać nieskomplikowane rozszerzenie z klasy. Jak widać w 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 użyciem:
class Sealed : ADOBE_FINAL( Sealed )
{//...
};
Podczas gdy pozwala na rozszerzenie, jeśli naprawdę go wymusisz:
class SealBreaker : public Sealed, ADOBE_FINAL( Sealed )
{
public:
SealBreaker() : adobe::implementation::final<Sealed>(), Sealed() {}
};
To ograniczy użytkowników od omyłkowo to zrobić.
EDIT :
Nadchodzący standard C++11 pozwala zaprzyjaźnić się z argumentem typu o 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"
};
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-05-07 21:52:35
Znalazłem prostą sztuczkę, aby zadeklarować parametry szablonu jako znajomych:
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
Nie wiem jednak, jak mogłoby to pomóc w zdefiniowaniu alternatywnej wersji uszczelniacza klasy.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-04-10 00:36:58
Czy naprawdę musisz to robić? Jeśli chcesz uniemożliwić komuś korzystanie z twojej klasy, po prostu dodaj komentarz i spraw, aby Destruktor nie był wirtualny.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-03-31 19:30:22