2012-09-04 13 views
5

Duplicar posible:
Inline functions in C++¿Qué sucede si implemento una clase en el archivo de encabezado?

¿Qué hacer si el compilador implemento completamente una clase en su archivo de cabecera? Un ejemplo típico sigue:

class MyException 
{  
public: 
    explicit MyException(const char* file, int line) file(file), line(line) {}; 
    const char* getFile() const { return file }; 
    int getLine() const { return line }; 
private: 
    const char* const file; 
    const int line; 
}; 

Mi intención es utilizar la clase como esta: throw MyException(__FILE__, __LINE__).

Incluyo este archivo de encabezado en cada archivo .cpp. Supongo que el compilador compilará la clase tantas veces como esté definida e incluirá el código máquina (idéntico) en cada archivo de objeto que produzca. Ahora, ¿qué hará el enlazador? Intenté un ejemplo más simple (sin todos esos molestos const) y compiló bien.

¿Qué pasaría si, en lugar de una clase simple, implementara una función C de tres pantallas en un archivo de cabecera? Y la pregunta final, ¿debería dividir mi ejemplo en archivos .h y .cpp?

+7

Los métodos implementados en la definición de clase están en línea. –

+1

Para una clase corta como esta, no tiene sentido dividirla en .h y .cpp. – alfa

+0

Funcionará bien, siempre que no incluya su excepción en 2 bibliotecas y ejecute esta excepción a través de los límites de la biblioteca en un sistema Linux. El tiempo de ejecución considerará la versión 2 de la excepción como diferente y una captura (MyException &) en la biblioteca A podría no funcionar para un throw MyException de la biblioteca B – gastush

Respuesta

3

Una definición de clase en sí no produce ningún código. Simplemente muestra a los usuarios de la clase cómo se distribuye, para que puedan generar el código apropiado para manipularlo.

Son las funciones miembro de la clase las que generan el código. Cuando define una función miembro dentro de la definición de clase, le da a la función una declaración implícita de inline.

una llamada de función puede ser compilado y enlazado en una de dos maneras:

(1) Una sola copia del código de función con una instrucción de montaje retorno al final se puede colocar en la imagen, y una llamada se pueden colocar instrucciones de ensamblaje (junto con el paso de param y la transferencia de valor de retorno) en el sitio de la llamada para transferir el control a este código.

o

(2) Una copia completa de la implementación de la función puede sustituir toda la llamada a la función en el lugar de llamada.

Una función declarada inline es una recomendación para el compilador para hacerlo de la segunda manera. Además, una declaración inline permite que la función se defina en varias unidades de traducción (para que pueda colocarse en un archivo de encabezado compartido). Para que el compilador tenga la opción de implementar el segundo método, necesita una copia de la implementación de la función en tiempo de compilación. Esto no está disponible si la implementación de la función está en una unidad de traducción extranjera.

También se debe tener en cuenta que los compiladores modernos hacen cosas complicadas con funciones declaradas en línea. Ver:

http://gcc.gnu.org/onlinedocs/gcc/Inline.html

+2

Hay una diferencia sutil entre una función en línea y una función en línea. –

+0

Es importante agregar que las funciones en línea _may_ se pueden expandir en línea. No lo harán _serán ... Pero las funciones no en línea también pueden expandirse en línea. – jcoder

+1

El significado más importante de 'inline' es que la función se puede definir en múltiples unidades de traducción y el compilador/enlazador/lo que sea necesario para producir una sola copia en el programa final. Esto es directamente relevante para la pregunta (ya que los miembros de la clase están implícitamente en línea, y por lo tanto la definición de clase puede incluirse desde múltiples unidades de traducción), mientras que cualquier efecto que pueda tener sobre la decisión de poner en línea llamadas de función particulares no es relevante. –

3

Todos los métodos serán los métodos en línea. Puede perder un poco de tiempo en la compilación general, pero está bien. Hasta donde sé, sé que el único problema que puede ocurrir es que tengas una variable de miembro estático y sin costo. Luego tiene que asignarle un lugar de almacenamiento (coloque una definición y un valor inicial si lo desea) presumiblemente en un .cpp o de lo contrario obtendrá errores del enlazador sobre la definición múltiple.

He visto proyectos de solo encabezado que tenían solo la función main() en un CPP, pero que tenían muchas plantillas.

3

Cuando implementa funciones miembro dentro de un archivo de cabecera, todas esas funciones se vuelven implícitamente inline.

¿Qué significa esto y qué implicaciones tiene?

Como por, C++ 03 Standard §7.1.3/4:

  • insinúa al compilador que es preferible a la usual sustitución de cuerpo de la función en el punto de llamada mecanismo de llamada de función.
  • Incluso si se omite la sustitución en línea, se siguen las otras reglas (especialmente w.r.t One Definition Rule) para inline.

Así Sí, cada unidad de traducción tendrá la definición de los inline funcionarán.Esta puede resultado en el incremento en el tamaño de los archivos binarios.

Por lo general, cualquier buen compilador corriente principal se sustituye cuerpo de la función en el punto de llamada si es necesario, por lo que marca funciones inline simplemente para # 1 no es realmente una buena idea, pero si usted desea hacer su intención claro para los usuarios de su clase, puede hacerlo definiendo las funciones dentro del encabezado o marcando explícitamente sus funciones como inline.

¿Debo dividir mi ejemplo en .h y .cpp archivos?

Sí, ese es el modelo de compilación habitual que la mayoría de los proyectos utilizan, en donde se separa la interfaz (.h) de la aplicación (.cpp) .Los las interfaces son compartidos con los usuarios de su código como archivos de encabezado mientras que la implementación se proporciona en forma de archivos binarios. Para algunos medida esto proporciona una protección a su propiedad intelectual.
Esto se conoce como Separación Modelo.

C++ proyectos utilizando plantillas se suele utilizar su Inclusión Modelo en lugar del modelo de separación de los proyectos habituales C++.

Cuestiones relacionadas