命名空间作用域中的内联函数和类作用域中的静态函数

Inline Function in Namespace Scope and Static Function in Class Scope

本文关键字:作用域 静态函数 命名空间 函数      更新时间:2023-10-16

标题中两者是否有语义上的区别?

例如,我可以写

class Hi{
public:
  static void Print(){
    printf("hin");
  }
};

,

namespace Hi{
  inline void Print(){
    printf("hin");
  }
}

我当然假设这两个定义都在头文件中。这仅仅是风格的问题吗?

一个主要的区别是名称空间可以扩展,而类可以继承。这个区别对于c++ 03中的"枚举包装器"很重要。有些人强烈赞成在类中包装枚举,而另一些人强烈赞成在名称空间中包装枚举,而大多数人可能并不关心,也没有进行包装。

名称空间支持依赖于参数的查找,而类不支持(除了调用类定义中的友元函数,这时就真的是名称空间ADL起作用了)。

类支持访问控制(公共、受保护、私有),而名称空间不支持。对于名称空间,与私有访问相对应的技术是称为detailimpl之类的嵌套名称空间。但这只是惯例,不是编译器可以检查和强制的。

我想,既然以上是我首先想到的,它可能是最相关的。

值得注意的是:使用类作为一种虚假命名空间机制的库确实存在(特别是我遇到了这种类型的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的当前值。