2012-05-08 21 views
20

Soy desarrollador de Java y soy bastante nuevo en C++. Necesito implementar algún tipo de clase de utilidad, y estaba pensando en implementar los métodos como estáticos. Sin embargo, me encontré con this stackoverflow question sobre las funciones de espacio de nombres vs método estático, y las funciones de espacio de nombres de Apprently es el enfoque preferido. Entonces me gustaría saber si hay algún artículo o ejemplo sobre cómo implementar la función de espacio de nombres. Por ejemplo, ¿cómo debo declarar las funciones del espacio de nombres en el archivo de encabezado? ¿El encabezado solo debe contener definiciones de función como el archivo de encabezado de clase y las implementaciones deben estar en el archivo cpp, o debo implementar funciones en el archivo de encabezado inmediatamente?C++ Namespace Functions

Básicamente, estoy tratando de implementar una aplicación para analizar un archivo de texto que contiene algunos comandos. Así que estoy pensando en implementar métodos estáticos de ayuda para manejar el procesamiento de texto. E.g readCommand (línea de cadena). Por favor, avíseme si estoy en la dirección incorrecta. Gracias

+1

C++ establece una distinción muy clara entre las funciones y clases . No está claro a partir de su pregunta cuál le interesa usar. – Shep

+0

Hola Shep, gracias por el comentario. Agregué más detalles a mi pregunta. ¿Responde a tu pregunta? –

Respuesta

19

¿cómo debo declarar las funciones de espacio de nombres en el archivo de encabezado?

namespace MON { 
// extern: 
t_ret func(const t_param& pValue); 
// 'inline': 
inline t_ret inline_func(const t_param& pValue) { ... } 
} // << MON 

En caso de cabecera sólo contienen definiciones de funciones como el archivo de cabecera de la clase y las implementaciones deben estar en cpp, o debería aplicar de inmediato las funciones en el archivo de cabecera?

que depende de si desea que (inline) forme o se exporte. esto a menudo se reduce a minimizar las dependencias.

para expandir el exportador o procesos en línea:

que habría menudo favorecen una función extern para minimizar las dependencias en C++. esto es equivalente a separar la definición de la declaración en un método de clase:

file.hpp

namespace MON { 
// extern: 
t_ret func(const t_param& pValue); 
} // << MON 

file.cpp

#include "hefty_stuff.hpp" 

MON::t_ret MON::func(const t_param& pValue) { ... } 

Sin embargo, es en los momentos críticos para la definición para ser visible en algunos casos, a menudo para el rendimiento o cuando se conoce el tamaño es importante y el encabezado no se incluye en muchos lugares. por lo tanto, la variante inline también es una opción.

una función en línea aún se puede exportar, y puede estar en línea según lo solicitado; sin embargo, cualquier copia de función en línea puede fusionarse (específicamente, la implementación puede suponer que todas las definiciones son iguales y cualquier copia de la función innecesario).

con definiciones exportadas, puede restringir (o poner en cuarentena) selectivamente sus dependencias de inclusión. es decir, #include "hefty_stuff.hpp" no necesita estar en el encabezado para usar las funciones en file.hpp.


Básicamente, estoy tratando de implementar una aplicación para analizar un archivo de texto que contiene algunos comandos. Así que estoy pensando en implementar métodos estáticos de ayuda para manejar el procesamiento de texto.

bien, static debe evitarse aquí. C++ usa la regla de una sola definición. static resultará en muchas copias innecesarias. Por otra parte, un espacio de nombres en el anonimato es el enfoque C++ para la función de c static:

namespace { 
t_ret func(const t_param& pValue) { ... } 
} // << anon 

nota: espacios de nombres anónimos también pueden dar lugar a copias innecesarias. la razón por la que los usaría como sustituto de una función estática es si quiere o necesita desviarse de la regla de una definición, y no quiere declarar el símbolo en un ámbito que pueda 'resolverse'.


el punto final se refiere a template<> declaraciones. con plantillas, la definición debe ser visible donde se use, a menos que su compilador admita plantillas externas. para las plantillas, puede lograr la visibilidad de la definición de múltiples maneras. Por lo general, las personas simplemente declaran la definición en su lugar o agregan un encabezado para las definiciones que se incluyen al final del encabezado o según sea necesario. con plantillas, las funciones no necesitan declararse inline para evitar múltiples errores de definición.

+0

Muchas gracias Justin. ¿Podría explicar un poco más sobre el punto "potencialmente en línea o exportado", o señalarme algún artículo que debería leer sobre él? –

+2

@KHein yup - expandido – justin

+0

@Justin, olvidó mencionar las funciones de plantilla. – Griwes

1

¿cómo debo declarar las funciones de espacio de nombres en el archivo de encabezado?

namespace YourNamespace 
{ 
    void fun1(); 
    void fun2(); 
} 

En caso de cabecera sólo contienen definiciones de funciones como el archivo de cabecera de la clase y las implementaciones deben estar en cpp, o debería aplicar de inmediato las funciones en el archivo de cabecera?

Si sus funciones en el espacio de nombres son estáticas, puede implementar funciones en el archivo de encabezado, o debe implementarlas en un archivo cpp.

+0

No completamente correcto, puede implementar funciones no estáticas en el encabezado. – juanchopanza

+1

@juanchopanza: solo si los declaras 'en línea'. –

+0

@Kerrek SB: acepta –

12

Se puede declarar las funciones en la cabecera:

namespace A { 
    void foo(); 
} 

y poner en práctica en el .cpp:

namespace A { 
    void foo() { std::cout << "foo!"; } 
} 

También se puede poner la aplicación en la cabecera, asegurándose de declarar que inline para evitar romper el one definition rule:

namespace A { 
    inline void foo() { std::cout << "foo()!"; } 
} 

No e que poner la implementación en el encabezado significa que el código del cliente tiene una dependencia de compilación en la implementación, así como en los encabezados utilizados para la implementación. En el ejemplo anterior, el código del cliente ahora depende del encabezado, y si hacemos algo trivial como agregar un signo de admiración a la copia impresa, necesitamos volver a compilar, en lugar de volver a vincular, todo el código del cliente.

Es muy importante poner las implementaciones de las funciones de plantilla en la cabecera o en un archivo incluido en la cabecera, estos no pueden ir en el .cpp:

namespace B { 
    template <class T> 
    inline void foo(const T& t) { std::cout << t.name() << "\n"; } 
} 
+0

+1 para poner implementaciones de funciones de plantilla en el encabezado. La definición debe ser visible donde se use, a menos que su compilador admita plantillas externas. – milesma