namespace, classi e funzioni liberi - quando hai bisogno di nomi completi
-
28-09-2019 - |
Domanda
Nel mio esempio qui sotto, perché devo qualificare completamente il nome della funzione libera nella cpp per errori del linker evitare e perché funziona per la funzione di classe senza? Ci può spiegare la differenza?
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()
{}
Grazie per il vostro tempo e aiuto.
Soluzione
int FreeFunction(void);
è solo una dichiarazione, mentre il sotto è una definizione.
class CTest
{
public:
CTest();
~CTest();
};
Se si desidera fornire definition for an already declared entity in a namespace
(ad esempio in uno spazio dei nomi che racchiude), deve essere il nome completo.
EDIT2:
Qui c'è qualcosa che possa dare qualche maggiore chiarezza. Nota n direttiva using in questo codice.
namespace Test {
int FreeFunction(void); // declare
class CTest; // declare
}
int Test::FreeFunction(){return 0;} // define
class Test::CTest{ // define
};
int main(){}
EDIT 3: Dichiarazione vs definizione (C ++ 0x) $ 3,1 / 2-
Una dichiarazione è una definizione a meno che dichiara una funzione senza specificando il corpo della funzione (8.4) , contiene l'extern specificatore (7.1.1) o un linkage-specification25 (7.5) e né un inizializzatore né funzione-corpo, dichiara statica membro di dati in una definizione di classe (9.4), è un nome di classe Dichiarazione (9.1) , si tratta di un opaco-enum dichiarazione (7.2), oppure è una dichiarazione typedef (7.1.3), un dichiarazione using (7.3.3), un static_assert dichiarazione (clausola 7), un attributo dichiarazione (clausola 7), un vuoto dichiarazione (articolo 7), o using-directive (7.3.4).
Altri suggerimenti
Mentre FreeFunction
si risolverà per Test::FreeFunction
se fa riferimento ad essa o chiamare dopo aver fornito la linea using namespace Test;
, per quanto che definisce la funzione va, il compilatore non ha modo per sapere se si sta definendo un del tutto nuova funzione FreeFunction
di fuori di ogni spazio dei nomi, o se si sta definendo il Test::FreeFunction
già dichiarato. Le impostazioni predefinite del compilatore a pensare che si sta definendo una funzione completamente nuova.
Per CTest::CTest
, tuttavia, siete già riferimento alla la classe Test::CTest
, e dal momento che non c'è classe o spazio dei nomi CTest
al di fuori dello spazio dei nomi Test
, bene, il riferimento a CTest::anything
è inequivocabile. Quindi sa che le definizioni costruttore e distruttore si riferiscono alla classe CTest
in-namespace.
Credo che sia un piccolo prezzo da pagare, di dover Test::FreeFunction
scrittura.
Spero che questo aiuti!
Se non si qualificano definizione FreeFunction, il compilatore non sa per certo antere si desidera fornire implementazione per il già avanti dichiarato Test :: FreeFunction o per una FreeFunction separata nello spazio dei nomi corrente.
D'altra parte, c'è solo un modo per risolvere il nome CTest - come la definizione della classe dallo spazio dei nomi di prova. Così, non c'è bisogno di qualificare pienamente.
Tuttavia, se la risoluzione dei nomi CTest è ambiguo (dicono c'è un'altra classe CTest nello spazio dei nomi corrente pure), si dovrà qualificare pienamente le dichiarazioni di metodo.
Quando si implementa una funzione di solito è preferibile, trovo, ad aprire lo spazio dei nomi. Ricorda che puoi ri-aprire ...
// in Test.cpp
namespace Test
{
int FreeFunction()
{
return 0;
}
}