定义命名空间成员与自由功能,无需限定 [英] Defining namespaced member vs free functions without qualification
问题描述
我有时在嵌套命名空间中声明类,并且在定义它们的成员函数时,我不喜欢使用这些嵌套的命名空间名称来限定每个类,特别是如果它们是long-ish。
在我定义成员函数之前添加using namespace(或者,为了更精确的定位,使用some :: SomeClass)似乎不需要限定每个定义,但是我找不到在规范中的任何地方,保证这一点,我担心,它可能是一个行为,只适用于GCC。我注意到,似乎没有类似的机制,当定义自由函数(?)时跳过需要添加限定符。
作为一个例子,意思是:
标题:
// example.h
namespace SomeNamespace
{
class SomeClass
{
public:
void someMemberFunction();
};
void someFreeFunction();
};实施: code> // example.cpp
#includeexample.h
使用命名空间SomeNamespace;
void SomeClass :: someMemberFunction()
{
// OK:似乎定义了SomeNamespace :: SomeClass :: someMemberFunction(),
//没有限定它与SomeNamespace ::
}
void someFreeFunction()
{
//不是我们想要的;声明和定义:: someFreeFunction(),而不是
// SomeNamespace :: someFreeFunction()(很容易理解)
}
int main()
{
SomeClass a;
a.someMemberFunction(); // 好;它定义如上。
SomeNamespace :: someFreeFunction(); //未定义!
return 0;所以我的问题是上面的定义SomeClass :: someMemberFunction()的方式。法律,在规范中提到这里?如果合法,是否明智?它一定削减杂乱! :)
非常感谢:)
解决方案成员函数,编译器意识到它是一个必须属于以前声明的类的成员函数,所以它看起来像在标准9.3.5节中规定的类:
如果成员函数的定义在词法上超出了类
定义,那么成员函数名应该由其类
限定,使用::运算符。 [注意:在成员函数
定义中使用的名称(即在参数声明子句中包括
的默认参数(8.3.6),或在成员函数体中使用,
a构造函数(12.1),在mem初始化表达式
(12.6.2)中)如3.4所述。 ] [示例:
struct X {
typedef int T;
static T count;
void f(T);
};
void X :: f(T t = count){}
类 X
的成员函数 f
在全局范围中定义;
符号 X :: f
指定函数 f
是类 X
和
在 X
的范围内。在函数定义中,参数
T
指的是类中声明的typedef成员 T
c $ c> X
,
默认参数计数指的是在 X
中声明的静态数据成员计数
。 ]
基本上,你所做的是很好的。但是,当使用嵌套命名空间或具有长名称(或两者)的命名空间时,还有另一种(最好的)减少混乱的方法 - 定义别名:
namespace short_name = averylong :: nested :: namespacename;
I sometimes declare classes in nested namespaces and when it comes to defining their member functions, I prefer not to have to qualify each one with these nested namespace names, especially if they are long-ish.
Adding "using namespace " (or, for more precise targetting, "using ::SomeClass") before I define the member functions seems to obviate the need to qualify each definition, but I can't find anywhere in the spec that guarantees this, and I'm worried that it might be a behaviour that only works with GCC. I note that there doesn't appear to be a similar mechanism for skipping the need to add the qualifiers when defining free functions(?).
As an example of what I mean:
Header:
// example.h
namespace SomeNamespace
{
class SomeClass
{
public:
void someMemberFunction();
};
void someFreeFunction();
};
Implementation:
// example.cpp
#include "example.h"
using namespace SomeNamespace;
void SomeClass::someMemberFunction()
{
// OK: seems to define SomeNamespace::SomeClass::someMemberFunction(),
// even though we didn't qualify it with SomeNamespace::
}
void someFreeFunction()
{
// Not what we wanted; declares and defines ::someFreeFunction(), not
// SomeNamespace::someFreeFunction() (quite understandably)
}
int main()
{
SomeClass a;
a.someMemberFunction(); // Ok; it is defined above.
SomeNamespace::someFreeFunction(); // Undefined!
return 0;
}
So my question: is the above way of definining SomeClass::someMemberFunction() legal, and where in the spec is this mentioned? If legal, is it advisable? It certainly cuts down on clutter! :)
Many thanks :)
解决方案 When you define a member-function, the compiler realizes that it is a member-function that must belong to a previously declared class, so it looks that class up, as specified in Section 9.3.5 of the standard:
If the definition of a member function is lexically outside its class
definition, the member function name shall be qualified by its class
name using the :: operator. [Note: a name used in a member function
definition (that is, in the parameter-declaration-clause including
the default arguments (8.3.6), or in the member function body, or, for
a constructor function (12.1), in a mem-initializer expression
(12.6.2)) is looked up as described in 3.4. ] [Example:
struct X {
typedef int T;
static T count;
void f(T);
};
void X::f(T t = count) { }
The member function f
of class X
is defined in global scope; the
notation X::f
specifies that the function f
is a member of class X
and
in the scope of class X
. In the function definition, the parameter
type T
refers to the typedef member T
declared in class X
and the
default argument count refers to the static data member count
declared in class X
. ]
Basically, what you are doing is fine. However, there is another (preferable) way to cut down on the clutter when using nested namespaces, or namespaces with long names (or both) - define an alias:
namespace short_name = averylong::nested::namespacename;
这篇关于定义命名空间成员与自由功能,无需限定的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!