Crear un espacio de nombres de C ++ en el encabezado y la fuente (cpp)


88

¿Hay alguna diferencia entre envolver el contenido del encabezado y el archivo cpp en un espacio de nombres o envolver solo el contenido del encabezado y luego usar el espacio de nombres en el archivo cpp?

Por diferencia me refiero a cualquier tipo de penalización de rendimiento o semántica ligeramente diferente que pueda causar problemas o cualquier cosa que deba tener en cuenta.

Ejemplo:

// header
namespace X
{
  class Foo
  {
  public:
    void TheFunc();
  };
}

// cpp
namespace X
{
  void Foo::TheFunc()
  {
    return;
  }
}

VS

// header
namespace X
{
  class Foo
  {
  public:
    void TheFunc();
  };
}

// cpp
using namespace X;
{
  void Foo::TheFunc()
  {
    return;
  }
} 

Si no hay diferencia, ¿cuál es la forma preferida y por qué?

Respuestas:


37

El espacio de nombres es solo una forma de alterar la firma de la función para que no entren en conflicto. Algunos prefieren la primera forma y otros prefieren la segunda versión. Ambas versiones no tienen ningún efecto sobre el rendimiento del tiempo de compilación. Tenga en cuenta que los espacios de nombres son solo una entidad de tiempo de compilación.

El único problema que surge con el uso del espacio de nombres es cuando tenemos los mismos nombres de espacios de nombres anidados (es decir) X::X::Foo. Hacer eso crea más confusión con o sin usar palabras clave.


55

La diferencia entre el "espacio de nombres X" y "usar el espacio de nombres X" es que en el primero cualquier declaración nueva estará debajo del espacio de nombre, mientras que en el segundo no lo estará.

En su ejemplo, no hay una nueva declaración, por lo que no hay diferencia, por lo tanto, no hay forma preferida.


Depende del proyecto y del estilo. A menudo, hay un espacio de nombres principal para una gran cantidad de archivos en un módulo, y el segundo estilo tiene sentido.
Nicholas Wilson

8

No hay penalizaciones de rendimiento, ya que el resultado podría ser el mismo, pero poner su Fooen el espacio de nombres introduce implícitamente ambigüedad en caso de que tenga Foos en espacios de nombres diferentes. Puede obtener su código fubar, de hecho. Recomiendo evitar su uso usingpara este propósito.

Y tienes una perdida {después using namespace;-)


No lo llamaría perdido, ya que coincide con el cierre }al final. Sin embargo, llamaría a ese par de llaves redundantes;)
blubberdiblub

@blubberdiblub, se editó la pregunta, si marcó la versión original, que le llaman desvían ;-)
Michael Krelin - pirata informático

1

Si el segundo también se compila, no debería haber diferencias. Los espacios de nombres se procesan en tiempo de compilación y no deberían afectar las acciones en tiempo de ejecución.

Pero por cuestiones de diseño, lo segundo es horrible. Incluso si se compila (no estoy seguro), no tiene ningún sentido.


1
No creo que se compile, pero no porque haya una diferencia, sino porque hay un {
error

La diferencia es que Foo :: TheFunc () se declara en el espacio de nombres global, mientras que se define en el espacio de nombres X.
bert-jan

1

Foo :: TheFunc () no está en el espacio de nombres correcto en el caso de VS. Utilice 'void X :: Foo :: TheFunc () {}' para implementar la función en el espacio de nombres correcto (X).


La pregunta es un poco vieja, pero ¿sabes cuáles son las consecuencias de esto? es decir, ¿se encontrará con algún problema con la forma en que su caso VS declara las funciones en el espacio de nombres, pero las define fuera de él?
Adam Goodwin

1

En caso de que envuelva solo el contenido .h, debe escribir usando el espacio de nombres ... en el archivo cpp, de lo contrario, cada vez que trabaje en el espacio de nombres válido. Normalmente, envuelve archivos .cpp y .h, de lo contrario, corre el riesgo de utilizar objetos de otro espacio de nombres, lo que puede generar muchos problemas.


0

Creo que lo correcto aquí es usar el espacio de nombres para el alcance.

namespace catagory
{
    enum status
    {
      none,
      active,
      paused
    }
};

void func()
{
    catagory::status status;
    status = category::active;
}

0

Si está intentando usar variables de una a otra, le recomendaría externalizarlas y luego inicializarlas en el archivo fuente de esta manera:

// [.hh]
namespace example
{
   extern int a, b, c;
}
// [.cc]
// Include your header, then init the vars:
namespace example
{
   int a, b, c;
}
// Then in the function below, you can init them as what you want: 
void reference
{
    example::a = 0;
}
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.