“Usar el espacio de nombres” en los encabezados de C ++

En todos nuestros cursos de c ++, todos los profesores siempre using namespace std; justo después de #include s en sus archivos .h Esto me parece peligroso ya que al incluir ese encabezado en otro progtwig obtendré el espacio de nombre importado en mi progtwig, tal vez sin darme cuenta, con la intención o sin querer (la inclusión del encabezado puede estar muy anidada).

Así que mi pregunta es doble: ¿tengo razón en que el using namespace no debe usarse en los archivos de encabezado, y / o hay alguna forma de deshacerlo, algo así como:

 //header.h using namespace std { . . . } 

Una pregunta más en la misma línea: debe un archivo de encabezado #include todos los encabezados que necesita el archivo .cpp correspondiente, solo aquellos que son necesarios para las definiciones de encabezado y dejar el archivo .cpp el rest, o ninguno y declarar todo necesita como extern ?
El razonamiento detrás de la pregunta es el mismo que el anterior: no quiero sorpresas al incluir archivos .h .

Además, si estoy en lo correcto, ¿es este un error común? Me refiero a la progtwigción del mundo real y a los proyectos “reales” que existen.

Gracias.

Definitivamente NO deberías using namespace de using namespace en los encabezados precisamente por la razón que dices, que puede cambiar inesperadamente el significado del código en cualquier otro archivo que incluya ese encabezado. No hay forma de deshacer un using namespace que es otra razón por la que es tan peligroso. Normalmente solo uso grep o similar para asegurarme de que el using namespace no se llame en los encabezados en lugar de intentar algo más complicado. Probablemente los verificadores de código estático también lo señalan.

El encabezado debe incluir solo los encabezados que necesita comstackr. Una manera fácil de hacer cumplir esto es incluir siempre el encabezado de cada archivo fuente como lo primero, antes que cualquier otro encabezado. Entonces, el archivo fuente no podrá comstackrse si el encabezado no es autónomo. En algunos casos, por ejemplo, al referirse a clases de detalle de implementación dentro de una biblioteca, puede usar declaraciones forward en lugar de #include porque tiene control total sobre la definición de dicha clase declarada forward.

No estoy seguro de que lo llame común, pero definitivamente aparece de vez en cuando, generalmente escrito por nuevos progtwigdores que no están al tanto de las consecuencias negativas. Normalmente, solo un poco de educación sobre los riesgos se ocupa de cualquier problema, ya que es relativamente fácil de solucionar.

Punto 59 en “Estándares de encoding C ++” de Sutter y Alexandrescu: 101 Reglas, pautas y mejores prácticas “:

  1. No escriba los usos del espacio de nombres en un archivo de encabezado o antes de un #include. 108

Los títulos de todas las directrices están en http://www.gotw.ca/publications/c++cs.htm , pero los detalles son una lectura obligada para los desarrolladores de C ++.

Debe tener cuidado al incluir encabezados dentro de los encabezados. En proyectos grandes, puede crear una cadena de dependencia muy enredada que desencadene reconstrucciones más grandes / más largas de lo que realmente era necesario. Consulte este artículo y su seguimiento para conocer más sobre la importancia de una buena estructura física en los proyectos de C ++.

Solo debe incluir encabezados dentro de un encabezado cuando sea absolutamente necesario (siempre que se necesite la definición completa de una clase), y usar la statement directa siempre que pueda (cuando se requiere la clase es un puntero o una referencia).

En cuanto a los espacios de nombres, tiendo a usar el scope explícito del espacio de nombres en mis archivos de encabezado, y solo pongo un using namespace de using namespace en mis archivos cpp.

Consulte los estándares de encoding del Goddard Space Flight Center (para C y C ++). Eso resulta ser un poco más difícil de lo que solía ser; vea las respuestas actualizadas a las preguntas SO:

  • ¿Debo usar #include en los encabezados?
  • Encabezados autosuficientes en C y C ++

El estándar de encoding GSFC C ++ dice:

§3.3.7 Cada archivo de encabezado #include debe #include los archivos que necesita comstackr, en lugar de forzar a los usuarios a #include los archivos necesarios. #includes se limitará a lo que necesita el encabezado; otros #includes deben colocarse en el archivo fuente.

La primera de las preguntas con referencias cruzadas ahora incluye una cita del estándar de encoding GSFC C, y la razón fundamental, pero la sustancia termina siendo la misma.

Tiene razón en que using namespace de using namespace en el encabezado es peligroso. No sé cómo deshacerlo. Es fácil de detectar, sin embargo, solo busca using namespace de using namespace en los archivos de encabezado. Por esa última razón, no es común en proyectos reales. Los compañeros de trabajo más experimentados pronto se quejarán si alguien hace algo así.

En proyectos reales, las personas intentan minimizar la cantidad de archivos incluidos, porque cuanto menos incluyas, más rápido se comstackrá. Eso ahorra tiempo a todos. Sin embargo, si el archivo de cabecera supone que algo debe incluirse antes, debe incluirlo. De lo contrario, hace que los encabezados no sean autocontenidos.

Tienes razón. Y cualquier archivo solo debe incluir los encabezados necesarios para ese archivo. En cuanto a “¿está haciendo cosas mal comunes en proyectos del mundo real?” – ¡Oh si!

Como todas las cosas en la progtwigción, el pragmatismo debería conquistar el dogmatismo, IMO.

Mientras tome la decisión en todo el proyecto (“Nuestro proyecto usa STL extensivamente, y no queremos tener que anteponer todo con std ::.”), No veo el problema. Lo único que te arriesgas es colisiones de nombres, después de todo, y con la ubicuidad de STL es poco probable que sea un problema.

Por otro lado, si fue una decisión de un desarrollador en un único archivo de encabezado (no privado), puedo ver cómo generaría confusión entre el equipo y debería evitarse.

Creo que puedes usar ‘usar’ en los encabezados de C ++ de forma segura si escribes tus declaraciones en un espacio de nombres nested como este:

 namespace DECLARATIONS_WITH_NAMESPACES_USED_INCLUDED { /*using statements*/ namespace DECLARATIONS_WITH_NO_NAMESPACES_USED_INCLUDED { /*declarations*/ } } using namespace DECLARATIONS_WITH_NAMESPACES_USED_INCLUDED::DECLARATIONS_WITH_NO_NAMESPACES_USED_INCLUDED; 

Esto debería incluir solo las cosas declaradas en ‘DECLARATIONS_WITH_NO_NAMESPACES_USED_INCLUDED’ sin los espacios de nombres utilizados. Lo he probado en el comstackdor mingw64.

Con respecto a “¿Hay alguna manera de deshacer [a using declaration]?”

Creo que es útil señalar que el using declaraciones se ve afectado por el scope.

 #include  { // begin a new scope with { using namespace std; vector myVector; // std::vector is used } // end the scope with } vector myOtherVector; // error vector undefined std::vector mySTDVector // no error std::vector is fully qualified 

Entonces efectivamente. Al limitar el scope de la statement de using su efecto solo dura dentro de ese scope; está ‘deshecho’ cuando ese scope finaliza.

Cuando la statement using se declara en un archivo fuera de cualquier otro ámbito, tiene un scope de archivo y afecta a todo en ese archivo.

En el caso de un archivo de encabezado, si la statement using está en el scope del archivo, esto se extenderá al scope de cualquier archivo en el que se incluya el encabezado.

    Intereting Posts