Pregunta

Esta referencia posterior a la Regla una definición.

Wikipedia es bastante malo en explicar cómo ponerlo en práctica

¿Dónde puedo encontrar buenos Recursos sobre las pautas a seguir en C ++ .NET?

¿Fue útil?

Solución

La regla de una definición básicamente significa que una variable / función sólo puede estar ubicado en un lugar en el espacio de direcciones del ejecutable compilado. Una forma de pensar en ella mientras se compila, hay una gran variedad de memoria que se utilizará en el programa compilado (código objeto), y una tabla de consulta para hacer referencia a ubicaciones variables / funciones. Esto se realiza a nivel de cada proceso. Supongamos que el siguiente es un programa simple:

file1.cpp

int square(int x); // this is a declaration
extern int someVariable; // this is a declration

void square(int x)  // this is a definition
{
    return x * someVariable;
}

file2.cpp

int square(int x); // this is a declaration

int someVariable; // this is a definition    
void main()
{
    someVariable = 12;
    someVariable = square(4);
}       

Cuando se inicia el compilador compilar el código objeto, se lee en las declaraciones, y pone algo en su tabla. Al final de la compilación file1.cpp, que va a terminar con algo como esto:

declarations:
    square (XX): function that returns int, and takes a single int as parameter [4 bytes]
    someVariable (YY): integer [4 bytes]
data:
    12 34 56 78 aa XX XX XX XX ab cd
definition:
    square: starts at address 0

Esto supone que la función se compila a esas instrucciones de montaje particulares. A la hora del enlazador, XX XX XX XX que se reemplazarán por la dirección de someVariable.

archivo2 termina algo como:

declarations:
    square (XX): function that returns int, and takes a single int as parameter [4 bytes]
    someVariable (YY): integer [4 bytes]
data:
    00 00 00 00 12 34 56 78 12 34 56 YY YY YY YY 23 21
definitions:
    someVariable: starts at address 0
    main: starts at address 4

Y en este caso, el YY será reemplazado por la dirección de la plaza.

Aquí es donde el enlazador entra en juego. El trabajo del enlazador es ir a través de la lista, y construir una tabla de donde todo está en el espacio de direcciones del programa en tiempo de compilación. Sin embargo, no es un problema si dos archivos de objetos tienen la misma definición de una variable cuando se trata de vincular. Si había dos definiciones de someVariable en el ejemplo anterior, entonces no sabría qué reemplazarla con YY. Del mismo modo, si hay no definición, a continuación, se producen errores de vinculador feas.

La "solución" a la regla es crear particiones en el archivo de este tipo que tiene definiciones sólo en archivos .cpp, y tienen declaraciones de las cosas en sus archivos .h, por lo que el ejemplo anterior se convertiría en:

file1.cpp

#include "file2.h"

void square(int x)  // this is a definition
{
    return x * someVariable;
}

file1.h

int square(int x); // this is a declaration

file2.cpp

#include "file1.h"

int someVariable; // this is a definition    
void main()
{
    someVariable = 12;
    someVariable = square(4);
}

file2.h

extern int someVariable;

Tenga en cuenta que este es un ejemplo muy simple, y que no se aplica realmente en .NET ya que no existe un concepto de una distinción entre una declaración y definición.

Otros consejos

La forma más fácil de cumplir con la regla de una definición es poner la definición en un archivo .cpp en lugar de la cabecera.

La gente a veces ponen las definiciones en las cabeceras usando macros y / o condicionales del preprocesador para que el objeto o función definida sólo en una unidad de compilación. Pero es más fácil por lo general (y sin duda más comprensible) que sólo hay que poner la definición en un archivo .cpp.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top