2010-06-17 15 views
10

Mientras estaba leyendo la respuesta aceptada de this question, tenía la siguiente pregunta:¿Una excepción a la regla de "solo una implementación"?

Por lo general, los métodos están definidos en los archivos de cabecera (.hpp o lo que sea), y la aplicación en los archivos de origen (.cpp o lo que sea).

Una de las principales razones por las que es una mala práctica incluir un "archivo fuente" (#include <source_file.cpp>) es que su implementación de métodos se duplicaría, lo que provocaría errores de enlace.

Cuando uno escribe:

#ifndef BRITNEYSPEARS_HPP 
#define BRITNEYSPEARS_HPP 

class BritneySpears 
{ 
    public: 

    BritneySpears() {}; // Here the constructor has implementation. 
}; 

#endif /* BRITNEYSPEARS_HPP */ 

Él está dando la aplicación del constructor (en este caso una implementación "vacío", pero aún así).

Pero por qué entonces incluir este archivo de encabezado varias veces (aka. En diferentes archivos de origen) se no generar un error de "definición duplicada" en tiempo de enlace?

+0

Aquí hay otra respuesta acerca de la regla de definición en línea: http://stackoverflow.com/questions/908830/isnt-cs-inline-totally-optional/910686#910686 –

+2

BTW, BritneySpears tiene un vínculo débil en su código. Como en la vida real :) –

+1

Deja a Britney sola –

Respuesta

13

Las funciones en línea son excepciones a la "regla de una definición": se le permite tener implementaciones idénticas de ellas en más de una unidad de compilación. Las funciones están en línea si están declaradas inline o implementadas dentro de una definición de clase.

+0

¿Estás seguro de esto? Si compilo esto y miro el desmontaje, veo claramente una instrucción de "llamada". Entonces, no hay línea. Además, puedo declarar funciones recursivas en la definición de clase, incluirlas múltiples archivos .cpp y no obtener ningún error de enlazador. ¿Cómo pueden ser insertados? (Podría ser un comportamiento específico de MS, sin embargo) – Niki

+1

@nikie: Aunque puede haber una instrucción de llamada allí, el vinculador trata las funciones de manera diferente, consulte el enlace en mi respuesta para más detalles. – sharptooth

+3

@nikie "función en línea" no significa que las llamadas están en línea. Simplemente significa que reciben un tratamiento especial por parte del vinculador, por lo que se permiten múltiples definiciones de ellos en el programa. Para que las llamadas estén en línea esto es necesario, porque solo entonces, múltiples TU pueden ver el código y no solo una TU. Pero no es suficiente: el compilador aún puede usar instrucciones de llamada simple. –

2

Porque es una función "en línea". Las funciones en línea pueden incluirse desde los encabezados tantas veces como desee y no causan errores de enlazador de definición duplicados.

El compilador también tratará de llevarlos en línea por lo que, en su ejemplo anterior, el compilador tratar y eliminar la llamada al constructor por completo.

7

Las funciones miembro con implementación dentro de la definición de clase se tratan como funciones en línea. Las funciones en línea están exentas de una regla de definición.

Específicamente cuando el vinculador ve dos funciones en línea con la misma firma, las trata como si fuera la misma función y simplemente selecciona una de ellas. Esto puede llevar to really weird hard to detect problems.

Cuestiones relacionadas