2010-01-17 9 views
26

Tengo algunas funciones en línea contenidas dentro de un espacio de nombres en un archivo de encabezado y actualmente no estoy en posición de moverlas a un archivo cpp. Algunas de estas funciones en línea utilizar las constantes mágicas, por ejemplo:Ocultar constantes privadas en un encabezado de espacio de nombres en línea

// Foo.h 
namespace Foo 
{ 
    const int BAR = 1234; 

    inline void someFunc() 
    { 
     // Do something with BAR 
    } 
} 

Sin embargo, quiero hacer estas constantes mágicas privada - alguna idea de cómo? Lo primero que pensé fue utilizar un espacio de nombres en el anonimato por lo tanto:

// Foo.h 
namespace Foo 
{ 
    namespace 
    { 
     // 'private' constants here 
     const int BAR = 1234; 
    } 

    inline void someFunc() 
    { 
     // Do something with BAR 
    } 
} 

Sin embargo, esto no funciona y Foo::BAR está disponible para cualquier archivo CPP que incluye Foo.h? ¿Hay alguna manera de hacerlo sin crear un archivo cpp de implementación?

Respuesta

28

No puede, los espacios de nombres anónimos funcionan para la unidad de traducción en la que están definidos (o incluidos en su caso).
usted podría considerar su traslado a un espacio de nombres detail para indicar al usuario que son datos internos:

namespace foo { 
    namespace detail { 
     int magic = 42; 
    } 

    // ... use detail::magic 
} 
+4

Este es también el uso de la convención impulso. Funciona bien siempre y cuando le digas a todo el mundo: "Nunca ingreses un espacio de nombres de detalles", que la mayoría no haría de todos modos. – GManNickG

3

ponerlos en un espacio de nombres especial o nombre de ellos especialmente, en combinación con una convención proyecto que tales cosas no son -public:

namespace foo { 
    namespace detail { // as in "implementation details" 
    inline int answer() { return 42; } 
    const int perfect = 28; 
    } 
    std::string _question(); // not part of foo's "public interface" by convention 

    int this_is_public() { 
    using namespace detail; // now don't have to prefix detail:: 
    return answer() + perfect + _question().length(); 
    } 
} 

cualquier persona que use nombres documentados como no públicos será eludir cualquier "protección" intenta; que resalta la verdadera preocupación: documentar qué es parte de la interfaz pública y en qué se puede confiar.

Los espacios de nombres sin nombre resuelven un problema diferente: obtener nombres únicos para una UT en particular. Ellos no ayudarán aquí.

16

¿Qué tal:

namespace Foo { 
    class foo_detail { 
    private: 
     enum { 
      BAR = 1234, 
     }; 

     friend void someFunc(); 
    }; 

    inline 
    void someFunc() { 
     // something with foo_detail::BAR 
    } 
} 

Esto hace que la constante no accesible para cualquier otra persona que las funciones se marquen como amigos. Puede hacer que la clase no sea construible haciendo que el constructor sea privado para asegurarse de que nadie intente instanciar la clase.

Cuestiones relacionadas