Frage

Dieser Beitrag Bezug auf die One Definition Rule.

Wikipedia ist ziemlich schlecht auf zu erklären, wie es implementieren

Wo finde ich gute Ressourcen über Richtlinien in C ++ folgen?

War es hilfreich?

Lösung

Die eine Definitionsregel bedeutet im Grunde, dass eine Variable / Funktion kann nur an einer Stelle im Adressraum der kompilierte ausführbaren Datei befindet. Eine Möglichkeit, daran zu denken ist, während Sie kompilieren, gibt es eine Reihe von Speichern in dem kompilierten Programm (Objektcode) verwendet werden soll, und eine Lookup-Tabelle Variable / Funktion Stellen zu verweisen. Dies wird auf einer Pro Prozessebene durchgeführt. Nehmen wir an, dass die folgende ist ein einfaches Programm:

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);
}       

Wenn der Compiler startet den Objektcode kompiliert wird, liest es in den Erklärungen und legt Sache in seiner Tabelle. Am Ende des file1.cpp kompiliert, wird es mit etwas am Ende wie folgt:

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

Dies setzt voraus, dass die Funktion auf diese spezielle Montageanleitung zusammengestellt wird. Bei Linker Zeit wird XX XX XX XX durch die Adresse des somevariable ersetzt bekommen.

File2 endet so etwas wie:

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

Und in diesem Fall wird die YY durch die Adresse der quadratischen ersetzt werden.

Das ist, wo der Linker ins Spiel kommt. Die Aufgabe des Linkers durch die Liste zu gehen, und baut eine Tabelle, wo alles ist in dem Adressraum des Programms bei der Kompilierung. Allerdings gibt es ein Problem, wenn zwei Objektdateien die gleiche Definition einer Variablen, wenn es zu verbinden versucht. Wenn es zwei Definitionen von somevariable in dem obigen Beispiel, dann würde es nicht wissen, was YY mit zu ersetzen. Ebenso, wenn es nicht Definition, dann erhalten Sie hässlich Linkerfehler.

Die „Lösung“ für die Regel ist, die Dateien so partitionieren, dass Sie Definitionen nur in CPP-Dateien und haben Erklärungen der Dinge in Ihren H-Dateien, so dass das obige Beispiel würde:

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;

Beachten Sie, dass dies ein unglaublich einfaches Beispiel, und dass es nicht wirklich in .NET gilt, da es kein Konzept einer Unterscheidung zwischen einer Erklärung und Definition.

Andere Tipps

Der einfachste Weg, mit dem einer Definitionsregel zu erfüllen ist die Definition in einer CPP-Datei anstelle des Headers zu setzen.

manchmal Menschen Definitionen in Header setzen Makros und / oder Prä-Prozessor conditionals Verwendung nur in einer Übersetzungseinheit definiert das Objekt oder die Funktion zu machen. Aber es ist einfacher in der Regel (und sicherlich verständlich) nur setzt die Definition in einer CPP-Datei.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top