命名空间范围内的内联函数和类范围中的静态函数

时间:2015-05-23 15:15:06

标签: c++

标题中两者之间是否存在语义差异?

例如,我可以写,

class Hi{
public:
  static void Print(){
    printf("hi\n");
  }
};

但是,

namespace Hi{
  inline void Print(){
    printf("hi\n");
  }
}

我当然假设这两个定义都在标题中。这只是风格问题吗?

2 个答案:

答案 0 :(得分:1)

主要区别在于可以扩展名称空间,而可以继承类。这种差异对于" enum包装"在C ++ 03中。有些人强烈赞成在类中包装枚举,而其他人则强烈赞成将它们包装在命名空间中,而大多数人都不关心并且没有包装。

命名空间支持依赖于参数的查找,而类不是(除了在类定义中定义的友元函数的调用,然后它真正命名空间ADL)。

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

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

值得注意的是:使用类作为一种虚假命名空间机制的库确实存在(特别是我遇到了那种类型的XML解析器库),但它们非常罕见,我怀疑除了可能的上述枚举包装外,任何新的库都会这样做,但是C ++ 11的范围枚举使得它变得不那么重要了。

答案 1 :(得分:1)

虽然第一个示例中的类充当临时命名空间,但差异不仅限于样式。

例如,静态成员函数可以访问类的私有成员,例如同一个类的其他静态函数,类中定义的私有类型,以及类中定义的私有静态变量。

您可以使用在翻译单元范围内定义的名称空间和静态非成员函数/变量来模拟许多此行为。但是,当类的非静态成员需要与静态成员函数共享对私有成员的访问时,仿真将不完整。在这种情况下,您需要提供额外的功能来将私有成员公开给非成员,而成员函数则可以免费获得。

以下是基于您的代码的示例:

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 times\n", count);
    }
};

如果您想使用命名空间模拟上述行为,则需要声明您的Hi::Print是某个类的朋友,或者提供公共函数以获取count的当前值。