简体   繁体   English

名称空间,类和自由函数 - 何时需要完全限定名称

[英]namespaces, classes and free functions - when do you need fully qualified names

In my example below, why do I have to fully qualify the name of the free function in the cpp to avoid linker errors and why does it work for the class function without? 在下面的示例中,为什么我必须完全限定cpp中自由函数的名称以避免链接器错误,为什么它不适用于类函数? Can you explain the difference? 你能解释一下这个区别吗?

ctest.h: ctest.h:

namespace Test
{
    int FreeFunction();

    class CTest
    {
        public:
            CTest();
            ~CTest();
    };
}

ctest.cpp: 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()
{}

Thanks for your time & help. 感谢您的时间和帮助。

int FreeFunction(void);  

is just a declaration whereas the below is a definition. 只是一个声明,而下面是一个定义。

class CTest 
{ 
    public: 
        CTest(); 
        ~CTest(); 
}; 

If you want to provide definition for an already declared entity in a namespace (eg in an enclosing namespace), it has to be fully qualified name. 如果要为definition for an already declared entity in a namespace提供definition for an already declared entity in a namespace (例如,在封闭的命名空间中),则必须是完全限定名称。

EDIT2: EDIT2:

Here is something that would give you some more clarity. 这是一些可以让你更清晰的东西。 Note no using directive in this code. 请注意此代码中没有using指令。

namespace Test { 
    int FreeFunction(void);   // declare

    class CTest;              // declare
} 

int Test::FreeFunction(){return 0;} // define
class Test::CTest{            // define
};

int main(){}

EDIT 3: Declaration vs Definition (C++0x) $3.1/2- 编辑3:声明与定义(C ++ 0x)$ 3.1 / 2-

A declaration is a definition unless it declares a function without specifying the function's body (8.4) , it contains the extern specifier (7.1.1) or a linkage-specification25 (7.5) and neither an initializer nor a function-body, it declares a static data member in a class definition (9.4), it is a class name declaration (9.1) , it is an opaque-enum-declaration (7.2), or it is a typedef declaration (7.1.3), a using-declaration (7.3.3), a static_assert-declaration (Clause 7), an attribute-declaration (Clause 7), an empty-declaration (Clause 7), or a using-directive (7.3.4). 声明是一个定义, 除非它声明一个函数而没有指定函数的主体(8.4) ,它包含extern说明符(7.1.1)或linkage-specification25(7.5),既不是初始化器也不是函数体,它声明了类定义中的静态数据成员(9.4), 它是类名声明(9.1) ,它是一个opaque-enum-declaration(7.2),或者是一个typedef声明(7.1.3),一个using声明( 7.3.3),static_assert声明(第7条),属性声明(第7条),空声明(第7条)或使用指令(7.3.4)。

While FreeFunction will resolve to Test::FreeFunction if you refer to it or call it after providing the using namespace Test; FreeFunction将解析为Test::FreeFunction如果你引用它或在提供using namespace Test;调用它 using namespace Test; line, as far as defining the function goes, the compiler has no way to know if you're defining an entirely new function FreeFunction outside of any namespace, or whether you're defining the already declared Test::FreeFunction . 直到定义函数,编译器无法知道你是否在任何命名空间之外定义一个全新的 FreeFunction 函数 ,或者你是否定义了已经声明的Test::FreeFunction The compiler defaults to thinking that you're defining an entirely new function. 编译器默认认为您正在定义一个全新的函数。

For CTest::CTest , however, you're already referring to the class Test::CTest , and since there's no class or namespace CTest outside of the Test namespace, well, the reference to CTest::anything is unambiguous. 但是,对于CTest::CTest ,您已经引用了类Test::CTest ,并且由于Test命名空间之外没有类或命名空间CTest ,所以对CTest::anything的引用是明确的。 So it knows that the constructor and destructor definitions refer to the in-namespace class CTest . 所以它知道构造函数和析构函数定义引用了命名空间类CTest

I think it's a small price to pay, to have to write Test::FreeFunction . 我认为这是一个很小的代价,必须编写Test::FreeFunction

Hope this helps! 希望这可以帮助!

If you don't qualify FreeFunction definition, the compiler does not know for sure anther you want to provide implementation for the previously forward-declared Test::FreeFunction or for a separate FreeFunction in the current namespace. 如果你没有限定FreeFunction定义,编译器肯定不知道你想要为先前的前向声明的Test :: FreeFunction或当前命名空间中的单独FreeFunction提供实现。

On the other hand, there's only one way to resolve the name CTest - as the class definition from the Test namespace. 另一方面,只有一种方法可以解析名称CTest - 作为Test命名空间中的类定义。 Thus, there's no need to fully qualify it. 因此,没有必要完全限定它。

However, if the CTest name resolution is ambiguous (say there's another CTest class in the current namespace as well), you will have to fully qualify the method declarations. 但是,如果CTest名称解析是不明确的(比如当前命名空间中还有另一个CTest类),则必须完全限定方法声明。

When implementing a function it is usually preferable, I find, to open the namespace. 在实现函数时,我发现打开命名空间通常是可取的。 Remember you can re-open them... 记住你可以重新打开它们......

// in Test.cpp
namespace Test
{
   int FreeFunction()
   {
       return 0;
   }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM