namespaces, classes et fonctions libres - quand avez-vous besoin des noms qualifiés
-
28-09-2019 - |
Question
Dans mon exemple ci-dessous, pourquoi dois-je saisir le nom complet de la fonction libre dans le cpp pour éviter les erreurs de l'éditeur de liens et pourquoi il travaille pour la fonction de classe sans? Pouvez-vous expliquer la différence?
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()
{}
Merci pour votre temps et aide.
La solution
int FreeFunction(void);
est juste une déclaration alors que le ci-dessous est une définition.
class CTest
{
public:
CTest();
~CTest();
};
Si vous voulez fournir definition for an already declared entity in a namespace
(par exemple dans un espace de noms enfermant), il doit être le nom complet.
EDIT2:
Voici quelque chose qui vous donnerait un peu plus de clarté. Remarque aucune directive à l'aide de ce code.
namespace Test {
int FreeFunction(void); // declare
class CTest; // declare
}
int Test::FreeFunction(){return 0;} // define
class Test::CTest{ // define
};
int main(){}
EDIT 3: Déclaration vs Définition (C ++ 0x) $ 3.1 / 2
Une déclaration est une définition à moins il déclare une fonction sans spécifiant le corps de la fonction (8.4) , il contient les extern spécificateur (7.1.1) ou liaison-specification25 (7.5) et ni un initialiseur ni fonction corps, il déclare statique membre des données dans une définition de classe (9.4), il est un nom de classe déclaration (9.1) , il est un ENUM-déclaration opaque (7.2), ou est une déclaration typedef (7.1.3), un en utilisant déclaration (7.3.3), un static_assert-déclaration (Article 7), un attribut de déclaration (Article 7), une déclaration vide (article 7), ou un à l'aide-directive (7.3.4).
Autres conseils
Alors que FreeFunction
résoudra à Test::FreeFunction
si vous référence à ou appelez après avoir fourni la ligne de using namespace Test;
, pour autant que définir la fonction va, le compilateur n'a aucun moyen savoir si vous définissez un entièrement nouvelle fonction FreeFunction
en dehors de tout espace de noms, ou si vous définissez l'Test::FreeFunction
déjà déclaré. Les paramètres par défaut du compilateur à penser que vous définissez une toute nouvelle fonction.
Pour CTest::CTest
, cependant, vous êtes déjà se référant à la Test::CTest
de classe, et comme il n'y a pas CTest
classe ou espace de noms en dehors de l'espace de noms Test
, eh bien, la référence à CTest::anything
est sans ambiguïté. Donc, il sait que le constructeur et les définitions destructor se réfèrent à la classe dans l'espace de noms CTest
.
Je pense qu'il est un petit prix à payer pour avoir à écrire Test::FreeFunction
.
Hope this helps!
Si vous ne vous qualifiez pas à la définition mainlibre, le compilateur ne sait pas pour anthères sûr de vouloir assurer la mise en œuvre pour le test :: mainlibre ou pour une mainlibre séparée précédemment avant déclarée dans l'espace de noms en cours.
Par contre, il n'y a qu'une seule façon de résoudre le nom CTest - comme la définition de classe de l'espace de noms de test. Ainsi, il n'y a pas besoin de se qualifier pleinement.
Cependant, si la résolution du nom CTest est ambigu (dire qu'il ya une autre classe CTest dans l'espace de noms en cours ainsi), vous devrez qualifier complètement les déclarations de méthode.
Lors de la mise en œuvre d'une fonction, il est généralement préférable, je trouve, d'ouvrir l'espace de noms. Rappelez-vous que vous pouvez les rouvrir ...
// in Test.cpp
namespace Test
{
int FreeFunction()
{
return 0;
}
}