命名空间作用域中的内联函数和类作用域中的静态函数
Inline Function in Namespace Scope and Static Function in Class Scope
标题中两者是否有语义上的区别?
例如,我可以写
class Hi{
public:
static void Print(){
printf("hin");
}
};
,
namespace Hi{
inline void Print(){
printf("hin");
}
}
我当然假设这两个定义都在头文件中。这仅仅是风格的问题吗?
一个主要的区别是名称空间可以扩展,而类可以继承。这个区别对于c++ 03中的"枚举包装器"很重要。有些人强烈赞成在类中包装枚举,而另一些人强烈赞成在名称空间中包装枚举,而大多数人可能并不关心,也没有进行包装。
名称空间支持依赖于参数的查找,而类不支持(除了调用类定义中的友元函数,这时就真的是名称空间ADL起作用了)。
类支持访问控制(公共、受保护、私有),而名称空间不支持。对于名称空间,与私有访问相对应的技术是称为detail
或impl
之类的嵌套名称空间。但这只是惯例,不是编译器可以检查和强制的。
我想,既然以上是我首先想到的,它可能是最相关的。
值得注意的是:使用类作为一种虚假命名空间机制的库确实存在(特别是我遇到了这种类型的XML解析器库),但它们非常罕见,而且我怀疑除了上面提到的枚举包装之外,任何新的库都不会这样做,然而,由于c++ 11的范围枚举,这一点变得不那么重要了。
尽管第一个示例中的类充当临时名称空间,但差异并不限于样式。
例如,静态成员函数可以访问类的私有成员,如同一类的其他静态函数、类内部定义的私有类型和类内部定义的私有静态变量。
您可以通过在翻译单元范围内定义的命名空间和静态非成员函数/变量来模拟许多这种行为。但是,当类的非静态成员需要与静态成员函数共享对私有成员的访问时,模拟将不完整。在这种情况下,您需要提供额外的功能来将私有成员公开给非成员,而成员函数则可以免费获得。
下面是一个基于你的代码的例子:
class Hi{
private:
// This static member variable is defined in a cpp file
static int count;
public:
Hi() { // Let's pretend concurrency does not exist
count++;
}
static void Print(){
printf("You said Hi %d timesn", count);
}
};
如果您想用名称空间模拟上述行为,您需要将Hi::Print
声明为类的友元,或者提供一个公共函数来获取count
的当前值。
- C++quit()函数中可能存在作用域问题
- 全局作用域中函数指针的赋值
- 在类函数中初始化外部作用域变量
- 不同作用域中的静态变量和全局变量
- 是同一作用域的函数部分中的函数调用
- 未在此作用域中声明的函数和变量 (C++)
- 函数作用域是静态变量还是线程本地变量在C++11中的第一个条目中初始化
- C++静态成员函数中静态变量的作用域
- 如何在 c++ 中创建一个可调试的文件作用域(静态?)类
- 模板类中静态函数或指针的作用域解析
- 函数作用域的静态非 Pod 对象初始化
- 键入安全枚举和作用域辅助函数
- 是块作用域静态或线程存储持续时间变量初始化失败的原因
- 为什么文件作用域静态变量必须初始化为零
- 使用文件作用域的c++静态函数
- 被视为依赖作用域的函数模板的函数作用域结构体的静态成员函数
- 局部作用域和函数作用域的区别
- 在包含作用域的函数调用期间持续的临时函数参数
- 名称空间作用域构造函数定义是否需要类限定的标识符
- 命名空间作用域中的内联函数和类作用域中的静态函数