2012-08-06 22 views
6
void foo() 
{ 
    bar();   // error: ‘bar’ has not been declared 
} 

void bar() 
{ 
} 

namespace N 
{ 
    void foo() 
    { 
     N::bar(); // error: ‘bar’ is not a member of ‘N’ 
    } 

    void bar() 
    { 
    } 
} 

class C 
{ 
    static void foo() 
    { 
     C::bar(); // works just fine 
    } 

    static void bar() 
    { 
    } 
}; 

¿Cuál es la razón detrás de esta incoherencia al tratar las llamadas a las funciones por encima de su declaración? ¿Cómo puedo hacerlo dentro de una clase, pero no dentro de un espacio de nombres o en un alcance global?funciones de llamada por encima de su declaración

+0

Tal vez, compilador pasa varias veces a través de implementaciones de métodos de clase dentro de declaración de la clase, mientras que "C" compilador pasa sólo una vez. Podría ser algún legado, ya que foo() es esencialmente la función C –

+0

¿Y cuál es el resultado después de eliminar la estática del vacío estático foo? – perilbrain

+0

@Anonymous, eso no cambia nada – SingerOfTheFall

Respuesta

3

Puede definir funciones miembro dentro de la clase, o después de la declaración de clase, o parte de cada una.

para conseguir algo de consistencia aquí, las reglas para una clase con funciones definidas en línea es que todavía tiene que ser compilado como si las funciones se definieron después de la clase.

Su código

class C { 
    static void foo() 
    { 
     C::bar(); // works just fine 
    } 

    static void bar() 
    {  } 
}; 

compila el mismo que

class C { 
    static void foo(); 
    static void bar(); 
}; 

void C::foo() 
{ C::bar(); } 

void C::bar() 
{  } 

y ahora no hay magia en la visibilidad, ya que las funciones pueden todos ver todo lo declarado en la clase.

0

Bueno, tal vez porque tiene su declaración de clase en un solo lugar, y el compilador puede obtener fácilmente la información de sus miembros.

Un espacio de nombre, por otro lado, puede tener sus cosas en toneladas de archivos diferentes, y no se puede esperar que el compilador las examine, porque no sabe dónde buscar en primer lugar.

Para evitar esto, simplemente use function prototypes.

0

no estoy seguro, pero mi pensamiento es que un class es un tanto un objeto (mal utilizado) en el que todos sus componentes internos trabajan juntos (en términos generales), su miembro definitivamente tendrá sus métodos.

Pero un espacio de nombres es diferente, las funciones no están relacionadas. Significa que una función no está diseñada para funcionar con todas las otras funciones dentro del espacio de nombres.

Por lo tanto, dividir las declaraciones y las definiciones es lo mejor que puede hacer.

If foo() necesidades bar() su más probable van a estar en el mismo archivo de declaración, y trabajarían de esa manera

1
  1. espacios de nombres pueden ser reabiertas y las cosas nuevas se pueden añadir en cualquier lugar. Las clases no se pueden volver a abrir; todos sus contenidos deben colocarse en el único lugar .

  2. Los prototipos de funciones son legales en espacios de nombres pero no en clases.

Puede escribir

namespace n 
{ 
    void foo(); 

    void bar() 
    { 
     foo(); 
    } 

    void foo() 
    { 
    } 
} 

Pero no

class C 
{ 
    void foo(); 

    void bar() 
    { 
     foo(); 
    } 

    void foo() 
    { 
    } 
} 

Así clases necesita de estas características mucho más y es mucho más fácil de implementar para ellos que para los espacios de nombres.

0

Ver la siguiente cita del ámbito de aplicación estándar de la clase

3.3.7 [basic.scope.class]

1) Las siguientes normas describen el alcance de nombres declarados en las clases. 1) El alcance potencial de un nombre declarado en una clase consta no solo de la región declarativa después del punto de declaración del nombre, sino también de de todos los cuerpos de funciones, argumentos predeterminados y refuerzos-o-ecualizadores no estáticos miembros de datos en esa clase (incluyendo tales cosas en clases anidadas).

2) Un nombre N usado en una clase S se referirá a la misma declaración en su contexto y cuando reevalúe en el alcance completo de S. No se requiere diagnóstico por una violación de esta regla.

typedef int c; 
enum { i = 1 }; 

class X { 
    char v[i]; // error: i refers to ::i 
       // but when reevaluated is X::i 
    int f() { return sizeof(c); } // OK: X::c 
    char c; 
    enum { i = 2 }; 
}; 
Cuestiones relacionadas