Пространства имен, классы и бесплатные функции - когда вам нужны полностью квалифицированные имена
-
28-09-2019 - |
Вопрос
В моем примере ниже, зачем мне полностью квалить имя свободной функции в CPP, чтобы избежать ошибок линкеров и почему он работает для функции класса без? Можете ли вы объяснить разницу?
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()
{}
Спасибо за ваше время и помощь.
Решение
int FreeFunction(void);
Это просто декларация, тогда как ниже - это определение.
class CTest
{
public:
CTest();
~CTest();
};
Если вы хотите предоставить definition for an already declared entity in a namespace
(например, в закрытом пространстве имен), он должен быть полностью квалифицированным именем.
Редактировать2:
Вот что-то, что даст вам еще немного ясности. Не обратите внимание, используя директиву в этом коде.
namespace Test {
int FreeFunction(void); // declare
class CTest; // declare
}
int Test::FreeFunction(){return 0;} // define
class Test::CTest{ // define
};
int main(){}
Редактировать 3: Декларация VS Определение (C ++ 0x) $ 3.1 / 2--
Декларация - это определение Если он не объявляет функцию без указания тела функции (8.4), он содержит спецификатор Extern (7.1.1) или спецификацию ссылок25 (7.5), а также инициализатор, ни функциональный корпус, он объявляет статический элемент данных в определении класса (9.4), Это объявление имени класса (9.1), это непрозрачный-enum-декларация (7.2), или это объявление Typedef (7.1.3), использование-декларация (7.3.3), static_assert-декларация (пункт 7), объявление атрибута (предложение 7), пустое объявление (пункт 7) или используемая Директива (7.3.4).
Другие советы
Пока FreeFunction
будет разрешаться Test::FreeFunction
если ты обратитесь к этому или позвоните После предоставления using namespace Test;
линия, насколько определяющий Функция идет, компилятор не имеет способов знать, если вы определяете совершенно новая функция FreeFunction
вне любого пространства имен, или определяете ли вы уже объявленные Test::FreeFunction
. Отказ Компилятор по умолчанию должен думать, что вы определяете совершенно новую функцию.
За CTest::CTest
, Однако, однако, вы уже ссылаясь на класс Test::CTest
, и так как нет класса или пространства имен CTest
вне Test
пространство имен, ну, ссылка на CTest::anything
недвусмысленно. Таким образом, он знает, что определения конструктора и деструктора относятся к классу пространства In-Image CTest
.
Я думаю, что это небольшая цена, чтобы заплатить, чтобы написать Test::FreeFunction
.
Надеюсь это поможет!
Если вы не вводите определение Freefunction, компилятор точно не знает, что вы хотите предоставить реализацию для ранее переполненного теста :: Freefunction или для отдельной бесплатной записи в текущем пространстве имен.
С другой стороны, есть только один способ разрешить имя CTEST - как определение класса из пространства имен тестирования. Таким образом, нет необходимости полностью квалифицировать его.
Однако, если разрешение имени CTEST неоднозначно (скажем, есть еще один класс CTEST в текущем пространстве имен), вам придется полностью квалифицировать декларации методов.
При внедрении функции обычно предпочтительнее, я нахожу, чтобы открыть пространство имен. Помните, что вы можете восстановить их ...
// in Test.cpp
namespace Test
{
int FreeFunction()
{
return 0;
}
}