2011-08-31 17 views
9

este código compila y ejecuta sin errores:¿Por qué puedo llamar al constructor privado desde? Ámbito global?

class foo{ 
    static foo *ref; 
    foo(){} 
    public: 
    static foo *getRef(){ 
     return ref; 
    } 
    void bar(){} 
}; 

foo* foo::ref = new foo; // the construcrtor is private! 

int main(int argc, const char *argv[]) 
{ 
    foo* f = foo::getRef(); 
    f->bar(); 
    return 0; 
} 

podría explicar por qué alguien puede ser llamado el constructor?

Respuesta

15

Ese ámbito no es global: los miembros estáticos están en el ámbito de clase, por lo que su expresión de inicialización también está en el ámbito de clase.

+4

De hecho, sustituya la expresión con 'foo * ref = new foo;' (note la ausencia de 'foo ::') para obtener un error de compilación! –

10

La respuesta es que no está disponible en el alcance global. El inicializador de un miembro estático se define como dentro de el alcance de clase, por lo que tiene acceso a los miembros privados.

§9.4.2/2 [...] La expresión del inicializador en la definición de un miembro de datos estáticos está en el alcance de su clase (3.3.6).

-2

Esta forma de inicialización de miembros estáticos no es necesaria en versiones anteriores de C++. Se hacen obligatorios en versiones posteriores de C++.

Y, esta forma de inicialización de miembros estáticos se utilizará generalmente para inicializar los miembros estáticos antes de la creación de cualquier objeto de clase.

(E.g) int MyClass::objectsCounter=0; 

Pero,

foo* foo::ref = new foo; 

esta declaración que se acaba de inicializar un miembro estático (que es de tipo puntero) mediante la creación de un nuevo objeto.

Y en este caso está iniciando un miembro privado llamando a un método privado de su propia clase.

Por lo tanto aquí no hay ninguna función del alcance del globo.

+0

-1 ¿A qué se refiere por versiones "anteriores" y "posteriores" * de C++? AFAIK, esto ha sido parte del diseño del lenguaje desde el primer estándar en 1998. Además, usar 'new foo' siempre crea un objeto. La declaración realiza 2 cosas: a) se crea una instancia de tipo 'foo'; yb) a 'foo :: ref' se le asigna un puntero al objeto recién asignado. –

+0

@ André Caron Gracias por sus comentarios. Modifiqué mi publicación. De hecho, solo quise decir esta información. Pero erróneamente entregué la información. En cuanto a C++ más antiguo y posterior: -, la información provista ahora se toma de LA REFERENCIA COMPLETA-HERBERT. –

+0

Si planea una programación profesional en C++, debería considerar usar [libros en C++ recomendados por la comunidad C++] (http://stackoverflow.com/questions/388242/the-definitive-c-book-guide-and-list). –

Cuestiones relacionadas