2010-11-08 16 views
5

Supongamos que estoy realizando un proyecto y tengo la mayor parte del proyecto en un espacio de nombres llamado Project. Defino una clase dentro del proyecto de espacio de nombres llamado MainProject.C++ usando Namespace en archivos de origen

En el archivo fuente, para implementar la clase, hago 'using namespace Project;' ¿o lo envuelvo en un nido de "espacio de nombres de proyecto {...}"?

Respuesta

7

Dada una cabecera "nh":

namespace n{ 
    extern void f(); 
} 

La siguiente no definir f() en espacio de nombres n (de aquí en adelante, me referiré a ella como n::f:

#include "n.h" 
using namespace n; 

void f(){ } 

Si intenta hacer referencia a n::f en cualquier lugar, obtendrá un error de tiempo de enlace. Lo anterior define una f en el espacio de nombres global. Esto define n::f:

#include "n.h" 
void n::f(){ } 

Esto también lo hace:

#include "n.h" 
namespace n{ 
    void f(){ } 
} 

pero tiene una desventaja en la que si escribe mal el nombre o la firma, se le agrega una nueva función para el espacio de nombres y dejar void n::f() indefinido, lo que lleva a un error de tiempo de enlace semi-molesto.

Cuando las clases están involucrados, las cosas son un poco diferentes:

namespace n{ 
    class c{ 
    void f(); 
    }; 
    extern c operator + (const c&, const c&); // I'll use Matthieu M.'s example 
} 

Esto estará bien, porque no hay mundial c:

#include "n.h" 
using namespace n; 
void c::f(){ } 

Pero la siguiente causará un tiempo de enlace error si intenta agregar dos c, por la misma razón que con el primer intento de definir n::f():

#include "n.h" 
using namespace n; 
c operator + (const c &a, const c &b){ /* blah blah */ } // define global + 

Este escenario también causará un error de tiempo de enlace (o tal vez incluso un error de compilación, dependiendo de donde se define ::c::f):

class c{ // a global c, defined in some header somewhere 
    void f(); 
}; 

#include "n.h" 
using namespace n; 
void c::f(){ } // define the global c::f (a possible redefinition) and n::c::f remains undefined! 
3

Ambos métodos están bien, es realmente una cuestión de gusto (o conflictos de nomenclatura). Normalmente no hago ninguna de las dos cosas y solo antepongo el espacio de nombres cuando sea necesario.

2

Es mejor volver a abrir el mismo espacio de nombres y luego proporcionar la implementación de la clase en lugar de en un espacio de nombres diferente (adjunto). Esto se debe principalmente a la modularidad y su perspectiva relacionada con los beneficios.

1

Hay problemas (sutiles) con la sintaxis using namespace xxx;. Entre los choques de nombres ...

En general, es mejor NO usarlo. Recomendaría volver a abrir el espacio de nombres en lugar de anteponer los identificadores con el nombre del espacio de nombres, pero es más una cuestión de gusto.

Ejemplo de emisión sutil:

// header 
namespace foo 
{ 
    struct Bar 
    { 
    explicit Bar(int i); 
    int x; 
    }; 
    Bar operator+(Bar lhs, Bar rhs); 
} 

// source 
#include "the header here" 

using namespace foo; 

Bar operator+(Bar lhs, Bar rhs) 
{ 
    return Bar(lhs.x + rhs.x); 
} 

que provoca un error de compilación.