Czy wskaźnik do członków może omijać poziom dostępu członka?
Nasz niesławny litb ma ciekawy artykuł na temat jak obejść kontrolę dostępu .
Jest to w pełni zademonstrowane przez ten prosty kod:
#include <iostream>
template<typename Tag, typename Tag::type M>
struct Rob {
friend typename Tag::type get(Tag) {
return M;
}
};
// use
struct A {
A(int a):a(a) { }
private:
int a;
};
// tag used to access A::a
struct A_f {
typedef int A::*type;
friend type get(A_f);
};
template struct Rob<A_f, &A::a>;
int main() {
A a(42);
std::cout << "proof: " << a.*get(A_f()) << std::endl;
}
Który kompiluje i uruchamia (wyjście 42
) z gcc 4.3.4, gcc 4.5.1, gcc 4.7.0 (zobacz komentarz użytkownika 1131467) i kompiluje z Clang 3.0 i Comeau C / C++ 4.3.10.1 w C++03 strict mode i MSVC 2005.
Zostałem zapytany przez Luchiana o tę odpowiedź , w której użyłem jej do uzasadnienia że to było legalne. Zgadzam się z Luchianem, że to dziwne, jednak zarówno Clang, jak i Comeau są bliskimi pretendentami do większości dostępnych" standardowych " kompilatorów (znacznie bardziej niż domyślnie MSVC)...
I nie mogłem znaleźć niczego w projektach standardów, które mam dostępne(n3337 jest ostatnią wersją, którą dostałem w ręce).
Więc... czy ktoś może uzasadnić, że jest to legalne czy nie ?2 answers
Tak, to legalne . Odpowiedni tekst znajduje się w §14.7.2/12, mówiący o jawnej instancji szablonu:
12 zwykłe reguły sprawdzania dostępu nie mają zastosowania do nazw używanych do określania jawnych instancji. [Uwaga: w szczególności argumenty i nazwy szablonów używane w deklaratorze funkcji (w tym typy parametrów, typy zwrotne i specyfikacje WYJĄTKÓW) mogą być typami prywatnymi lub obiektami, które normalnie nie byłyby dostępne i szablon może być szablonem członka lub funkcją członka, która normalnie nie byłaby dostępny. - Uwaga końcowa ]
Emhpasis mine.
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-03-28 12:35:52
Kod jest wyraźnie nielegalny (i wymaga diagnostyki w czasie kompilacji). W linii:
template struct Rob<A_f, &A::a>;
Wyrażenie A::a
uzyskuje dostęp do prywatnego członka A
.
Standard jest o tym bardzo jasny: "Kontrola dostępu jest stosowana
jednolicie do wszystkich nazw, niezależnie od tego, czy nazwy odnoszą się do
deklaracje lub wyrażenia."(§11/4, podkreślenie dodane). Ponieważ a
jest nazwą prywatną w A
, wszelkie odniesienia do niej poza A
są nielegalne.
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-03-28 12:32:45