简体   繁体   English

在其命名空间外定义的类成员函数

[英]Class member function defined outside its namespace

The following code compiles perfectly with the latest MSVC, GCC and CLang available at godbolt online compiler explorer site. 以下代码与godbolt在线编译器浏览器站点上提供的最新MSVC,GCC和CLang完美编译。 I wonder why: 我想知道为什么:

namespace ns
{
    struct Test
    {
        void foo();
    };
}

using namespace ns;

// Alert! Member function defined outside its namespace!
void Test::foo()
{
}

int main()
{
    ns::Test   obj;
    obj.foo();
    return 0;
}

cppreference claims that if a member function is defined outside its class, then it must be defined at the namespace of that class. cppreference声称如果在其类之外定义成员函数,则必须在该类的名称空间中定义它。 See the very top of the cppreference page about member functions . 请参阅有关成员函数的cppreference页面的最顶部。

But still, the compilers accept the code. 但是,编译器仍接受代码。 It's really unlikely that all three independent compilers have the same bug, right? 所有三个独立编译器都不太可能有相同的bug,对吧? So, is there a good reason behind them accepting such code? 那么,他们接受这样的代码背后有充分的理由吗?

Quoting C++17 (n4659) 12.2.1 [class.mfct]/1: 引用C ++ 17(n4659)12.2.1 [class.mfct] / 1:

A member function definition that appears outside of the class definition shall appear in a namespace scope enclosing the class definition. 出现在类定义之外的成员函数定义应出现在包含类定义的命名空间范围内。

This means it must be defined in the namespace which contains the class, or any parent namespace of that namespace. 这意味着它必须在包含该类的命名空间或该命名空间的任何父命名空间中定义。 In your case, it's defined in the global namespace, which does indeed enclose (indirectly) the class definition. 在您的情况下,它在全局命名空间中定义,它确实包含(间接)类定义。

12.2.1 Member functions [class.mfct] 12.2.1成员函数[class.mfct]

A member function may be defined (11.4) in its class definition, in which case it is an inline member function (10.1.6), or it may be defined outside of its class definition if it has already been declared but not defined in its class definition. 可以在其类定义中定义成员函数(11.4),在这种情况下,它是内联成员函数(10.1.6),或者如果已经声明但未在其中定义,则可以在其类定义之外定义它。类定义。 A member function definition that appears outside of the class definition shall appear in a namespace scope enclosing the class definition. 出现在类定义之外的成员函数定义应出现在包含类定义的命名空间范围内。

This does not mean the definition must appear in the immediately surrounding scope . 并不意味着该定义必须出现在直接围绕范围 It can appear in any enclosing namespace, even if that is several layers up. 它可以出现在任何封闭的命名空间中,即使这是几层。

However, this would be illegal: 但是,这将是非法的:

namespace a {
    struct X {
        void Y();
    };
}
namespace b { // not an enclosing namespace
    void X::Y()
    {
        std::cout << "Do a thing!\n";
    }
}

using namespace ns;

5) using-directive: From the point of view of unqualified name lookup of any name after a using-directive and until the end of the scope in which it appears, every name from ns_name is visible as if it were declared in the nearest enclosing namespace which contains both the using-directive and ns_name. 5)using-directive:从使用指令之后的任何名称的非限定名称查找的角度来看,直到它出现的作用域的结尾,ns_name中的每个名称都是可见的,就好像它是在最近的封闭中声明的那样包含using-directive和ns_name的namespace。

It means that in the current scope ns can be omitted from addressing something inside that namespace. 这意味着在当前作用域中,可以省略ns来解决该命名空间内的某些内容。

As such when you write this code: 因此,当您编写此代码时:

using namespace std;
vector<string> vectorofstrings;

You don't have to write 你不必写

std::vector<std::string> vectorofstrings;

The namespace of a class is the name of the class. 类的名称namespace是类的名称。 So if you have: 所以如果你有:

namespace aNamespace{

class aClass{
    int aMember;
    void aFunction();
};

}

Then the fully qualified lookup is ::aNamespace::aClass and a function must be defined as being part of void ::aNamespace::aClass::aFunction(){} 然后完全限定的查找是::aNamespace::aClass并且必须将函数定义为void ::aNamespace::aClass::aFunction(){}

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

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