resueltos relaciones objetos herencia entre ejercicios ejemplos codigo clases asociacion c++ templates c++11 language-lawyer using

objetos - relaciones entre clases c++



C++ 11: ¿Por qué se puede acceder a la plantilla de miembro privado fuera de clase? (2)

Esto es definitivamente un error de compilación, y en realidad uno que se conoce desde hace bastante tiempo: gcc.gnu.org/bugzilla/show_bug.cgi?id=47346 (reportado por primera vez en enero de 2011) y Clang # 15914 (reportado por primera vez en mayo de 2013). Su __tklass es claramente private , y el alias de la plantilla no está marcado como friend , por lo que este debería ser un simple error de acceso.

La reproducción más simple es del adjunto de ejemplo de Clang, esta versión se compila tanto en gcc 4.9.2 como en clang 3.5.0, aunque definitivamente no debería compilarse en ninguna de las dos:

class A { class B {}; }; template<typename> using T = A::B; T<void> t;

Sin embargo, Clang es estrictamente mejor que GCC en este frente, ya que este error en particular parece ocurrir solo con alias de plantilla. Una "solución alternativa" (si necesita algo así para los casos que el compilador permite de forma incorrecta ...) sería volver al aliasing de plantilla anterior a C ++ 11:

template <typename> struct T { using type = A::B; }; T<void>::type t;

Ese código falla correctamente para compilar con clang (error: ''B'' es un miembro privado de ''A''), pero todavía compila bien con gcc.

Me acabo de dar cuenta de que se puede acceder a una clase de plantilla privada anidada directamente fuera de la clase adjunta usando una directiva using :

class wrapper { private: template <typename T> class __tklass {}; class __klass {}; }; template <typename T> using tklass = wrapper::__tklass<T>; // Expected error but compiles OK // using klass = wrapper::__klass; // "Error: __klass is private" int main() { tklass<int> v1; // Expected error but compiles OK // wrapper::__tklass<int> v3; // "Error: __tklass is private" // wrapper::__klass v4; // "Error: __klass is private" }

Las líneas marcadas como "Error: __xxx es privado" informan correctamente un error cuando se descomentan. Pero las líneas con tklass se compilan sin ninguna queja del compilador.

Entonces, ¿por qué exactamente el compilador no tklass error tklass pesar de que wrapper::__tklass es privado? ¿Es por casualidad permitido por el estándar? De ser así, ¿no se consideraría una violación grave de acceso?

Intenté esto con gcc-4.9.2, clang-3.5.0 y visual studio 2013 express. Línea de comando de GCC:

g++ -std=c++11 -pedantic -Wall -Wextra -Wshadow myfile.cpp


Herb Sutter escribió hace mucho tiempo el artículo, cómo las funciones del miembro de la plantilla pueden proporcionar una puerta trasera en una clase: http://www.gotw.ca/gotw/076.htm (por favor revise el caso 4: "The Language Lawyer" , al final)

Puede darte la respuesta.

EDITAR: Tengo curiosidad, ¿cuáles fueron los motivos para votar negativamente? Cito el artículo: "¿Es esto un agujero en el mecanismo de control de acceso de C ++, y por lo tanto un agujero en la encapsulación de C ++? Esto demuestra una interacción interesante entre dos características de C ++: el modelo de control de acceso y el modelo de plantilla. parecen implícitamente "romper la encapsulación" en el sentido de que efectivamente proporcionan una forma portátil de eludir el mecanismo de control de acceso de clase ".

Parece ser una respuesta razonable. EDITAR FIN

Uno podría pasar mucho tiempo tratando de asegurar las interfaces por medios técnicos privados / protegidos, etc. Mi forma preferida es hacer un acuerdo entre todos los desarrolladores para usar reglas bien entendidas que cumplan con un enfoque menos sorpresivo. (EDITAR: Y verifique el código en contra de estas reglas usando los scripts code-reviews / reg-exp en forma regular)

"No intente encontrar una solución técnica para un problema social" B. Stroustrup