2011-02-16 9 views
18

¿Cuál es la diferencia entre vincular para incluir archivos en lugar de vincular a archivos lib?incluyen directorios en relación con el concepto de directorio de lib pregunta

Soy bastante nuevo en C/C++ y me cuesta entender la diferencia entre utilizar archivos include y un archivo lib estático para llamar a funciones. En mi opinión, los archivos include tienen funciones que uno puede llamar como los archivos .lib.

+1

¿Conoces la diferencia entre compilar y vincular? Esto podría ayudar a aclarar la respuesta. – sstn

Respuesta

28

En C++ (y C y otros lenguajes similares) una función se dice que tiene tanto una declaración y una definición.

La declaración es simplemente una breve declaración que declara que la función existe y cuál es su interfaz. Considere una función básica add que agrega dos enteros juntos. Su declaración podría ser similar a la siguiente:

int add(int, int); 

Esto significa que "existe una función add que toma dos números enteros y devuelve un entero". No especifica qué función tiene realmente, a pesar del hecho de que podemos hacer una buena suposición en función de su nombre.

La definición de la función es donde definimos exactamente lo que hace la función de . Esto podría ser lo que usted considera que es el código de función real. Uso de la función add como ejemplo:

int add (int a, int b) 
{ 
    return a + b; 
} 

Entonces, ¿cómo encaja esto con su pregunta? Bien, supongamos que tenemos una serie de funciones matemáticas en math.cpp:

// math.cpp 

int add (int a, int b) 
{ 
    return a + b; 
} 

int sub(int a, int b) 
{ 
    return a - b; 
} 

Y también supongamos que decidimos utilizar algunos de estos en nuestra función principal en main.cpp:

// main.cpp 

#include <iostream> 

int main (int argc, char* argv[]) 
{ 
    std::cout << "1 + 2 = " << add(1, 2) << std::endl; 
    std::cout << "8 - 3 = " << sub(8, 3) << std::endl; 
} 

Si intenta compilar main.cpp como está, se quejará de que no sabe qué son add y sub.Esto se debe a que intentas usarlos sin declarar que existen, que es exactamente para lo que es una declaración. Por lo tanto, puede hacer lo siguiente:

// main.cpp 

#include <iostream> 

int add(int, int); 
int sub(int, int); 

int main (int argc, char* argv[]) 
{ 
    std::cout << "1 + 2 = " << add(1, 2) << std::endl; 
    std::cout << "8 - 3 = " << sub(8, 3) << std::endl; 
} 

Esto funcionaría, pero no es muy flexible. Si agregamos una nueva función mul, tenemos que ir y agregar su declaración al main.cpp y cualquier otro archivo .cpp que lo use (lo cual es mucho trabajo si tiene muchos archivos .cpp). Entonces, lo que hacemos es colocar todas las declaraciones en un solo archivo (por ejemplo, math.h), por lo que solo tenemos que mantener la lista de declaraciones en un solo lugar. Luego, simplemente incluimos math.h en cualquier archivo que use las funciones matemáticas. Este es el propósito de los archivos de cabecera (a.k.a. incluir archivos).

Esto funciona muy bien, pero podría ser incluso mejor. Tal como está, tenemos un archivo main.cpp y un archivo math.cpp, los cuales se compilan cada vez que compila el programa *. Si sus funciones matemáticas no cambian para nada, seguramente es mejor compilarlas una vez e insertar las definiciones precompiladas en su ejecutable siempre que recompile main.cpp? Ese es exactamente el propósito de los archivos .lib. Contienen el código precompilado para las definiciones de las funciones relevantes. Aún necesita el archivo de inclusión para saber qué funciones existen en la lib.

El propósito de la etapa de vinculación de la compilación es tomar estas funciones precompiladas y las funciones que acaba de compilar, y enrollarlas juntas en un solo archivo ejecutable.

Básicamente, puede ver una lib estática como el código precompilado para una serie de funciones predefinidas, y su coincidencia incluye el archivo como una herramienta para permitir que cualquier código que desee utilizar esas funciones sepa cuáles están disponibles y cuál es su descripción es.


* Esto no es estrictamente cierto, pero es suficiente para nuestros propósitos aquí.

+1

Gracias por la explicación completa. ¿Esto significa que al crear bibliotecas, siempre tendremos que tener un archivo .h que haga referencia a todas las funciones? Entonces, por ejemplo, si creo un myLibrary.lib usando un grupo de archivos .cpp y un archivo .h para declarar mis funciones, tendría que incluir el archivo .h en cualquier programa en el que use mi biblioteca para hacer referencia a la biblioteca como así como la vinculación a myLibrary.lib? – foboi1122

+1

@ foboi1122: Básicamente tienes la idea, sí. Sin embargo, para aclararlo, hacerlo de esa manera (es decir, con un archivo incluido) no es un * requisito * (usted * puede * simplemente declarar sus funciones en el archivo en el que las usa, según mi último ejemplo de código), pero el estándar la práctica es usar una inclusión para simplificar la administración de código. – Mac

+0

gracias por aclarar eso para mí. Agradezco la ayuda de todos – foboi1122

2

Los archivos de inclusión suelen contener la declaración de un símbolo (una función, una variable). de este let el compilador saber que se define un nombre (en la cabecera) o en otro lugar (en el caso de una declaración):

a.h: 

void a_useful_function(); //declaration 

pero también puede tener una definición:

a.h: 

void a_useful_function() 
{ 
    //... do something 
} 

Las bibliotecas son una acumulación de funciones que típicamente se exponen por encabezados. El encabezado generalmente es la interfaz a una biblioteca con la que se vinculará.

Sin embargo, existen bibliotecas de encabezado único que tienen su código de declaraciones y definiciones en el mismo archivo.

Mencione incluir directorios en su pregunta. Los directorios de inclusión son los lugares donde el compilador busca resolver una directiva de preprocesador #include "a.h".

Pero también hay directorios de biblioteca donde el vinculador busca las bibliotecas necesarias que generalmente proporcionan implementaciones (definiciones) a las declaraciones en sus encabezados.

0

para proporcionar una respuesta más simple:

.lib son bibliotecas precompilados. si incluye una .lib, también debe incluir los archivos de encabezado .h/hpp, de modo que su compilador sepa cómo acceder a las funciones en .lib.

cuando compila su programa, todas las funciones utilizadas desde lib solo están vinculadas, se compilan de nuevo.

Cuestiones relacionadas