Namespaces, Klassen und freie Funktionen - wenn Sie brauchen voll qualifizierte Namen
-
28-09-2019 - |
Frage
In meinem Beispiel unten, warum habe ich vollständig den Namen der freien Funktion in der CPP zu vermeiden Linkerfehler zu qualifizieren und warum funktioniert es für die Klasse Funktion ohne? Können Sie den Unterschied erklären?
ctest.h:
namespace Test
{
int FreeFunction();
class CTest
{
public:
CTest();
~CTest();
};
}
ctest.cpp:
#include "ctest.h"
using namespace Test;
// int FreeFunction() -> undefined reference error
int Test::FreeFunction() -> works just fine
{
return 0;
}
CTest::CTest() -> no need to fully qualify name, i.e. Test::CTest
{}
CTest::~CTest()
{}
Vielen Dank für Ihre Zeit und Hilfe.
Lösung
int FreeFunction(void);
ist nur eine Erklärung, während die unter der Definition ist.
class CTest
{
public:
CTest();
~CTest();
};
Wenn Sie bieten definition for an already declared entity in a namespace
wollen (zum Beispiel in einer einschließenden Namespace), hat es voll qualifizierte Namen sein.
EDIT2:
Hier ist etwas, das Sie etwas mehr Klarheit geben würde. Hinweis kein using-Direktive in diesem Code.
namespace Test {
int FreeFunction(void); // declare
class CTest; // declare
}
int Test::FreeFunction(){return 0;} // define
class Test::CTest{ // define
};
int main(){}
EDIT 3: Erklärung vs Definition (C ++ 0x) $ 3.1 / 2-
Eine Erklärung ist eine Definition es sei denn, es erklärt, eine Funktion ohne Spezifizieren des Körpers Funktion (8.4) , enthält es die extern Spezifizierer (7.1.1) oder ein gestänge specification25 (7.5) und weder ein initializer noch ein Funktionskörper, erklärt sie eine statische Datenelement in einer Klassendefinition (9.4), ist ein Klassenname Erklärung (9.1) ist es ein opaque-ENUM-Deklaration (7.2), oder ist eine typedef Deklaration (7.1.3), ein Verwendung Deklaration (7.3.3), ein static_assert-Deklaration (Ziffer 7), eine Attributdeklaration (Ziffer 7), eine Leermeldung (Ziffer 7) oder eine using-Direktive (7.3.4).
Andere Tipps
Während FreeFunction
zu Test::FreeFunction
lösen, wenn Sie darauf verweisen oder nennen es nach der using namespace Test;
Linie bereitstellt, so weit wie definieren die Funktion geht, hat der Compiler keine Möglichkeit, zu wissen, ob Sie eine ganz neue Funktion FreeFunction
außerhalb eines Namespace sind definiert, oder ob Sie die bereits erklärt Test::FreeFunction
sind zu definieren. Der Compiler standardmäßig denken, dass Sie eine völlig neue Funktion sind zu definieren.
Für CTest::CTest
, aber du bist schon unter die Klasse Test::CTest
, und da es keine Klasse oder Namespace CTest
außerhalb des Test
Namespace, na ja, der Verweis auf CTest::anything
eindeutig ist. So ist es weiß, dass beziehen sich die Konstruktor und Destruktor-Definitionen in der in-Namespace-Klasse CTest
.
Ich denke, es ist ein kleiner Preis zu zahlen, zu schreiben Test::FreeFunction
zu haben.
Hope, das hilft!
Wenn Sie nicht FreeFunction Definition qualifizieren, der Compiler nicht weiß sicher anthere Sie Implementierung für die zuvor voraus erklärt Test :: FreeFunction oder für einen separaten FreeFunction im aktuellen Namensraum zur Verfügung stellen möchten.
Auf der anderen Seite gibt es nur einen Weg, den Namen CTest zu lösen - wie die Klassendefinition aus dem Test-Namespace. Somit gibt es keine Notwendigkeit, sie vollständig zu qualifizieren.
Wenn jedoch die CTest Namensauflösung nicht eindeutig ist (sagen, es ist eine andere CTest Klasse im aktuellen Namensraum als auch), Sie haben völlig die Methode Deklarationen.
Wenn Sie eine Funktion deren Umsetzung in der Regel vorzuziehen ist, finde ich, den Namensraum zu öffnen. Denken Sie daran, Sie können wieder öffnen sie ...
// in Test.cpp
namespace Test
{
int FreeFunction()
{
return 0;
}
}