为什么要在类中定义常量而不是命名空间?

时间:2011-05-09 21:46:19

标签: c++

  

可能重复:
  Static members class vs. normal c-like interface

我正在查看somebodies代码,并且在这样的类中定义了几十个常量:

// header file

class Defines
{
public:
    static const int Val1;
    static const int ValN;
    static const char* String1;
    static const char* StringN;
...
}

// .CPP
const char* Defines::String1 = "some value"
etc.

有没有理由这样做而不是使用命名空间? 是否存在一个优点/缺点

---------编辑----------

对不起,我显然应该明确地指出这一点,因为没有人从类的名称推断它 - 这是“定义”。即,这些常量与特定类没有关联,有一个专门创建的类只是为了保存常量而没有其他东西,这就是所有类定义包含的。

我的问题不是为什么你要把常量放在一个特定的类中,问题是将它们中的几十个一起收集并将它们放在一个中的任何价值它的唯一目的是聚集在一起常量,而不是在命名空间中将它们收集在一起,或者只是将它们一起收集在一个专门用于此目的的头文件中。

(项目中目前没有命名空间,因此在这种情况下,答案中提到的污染命名空间的潜在问题与此无关。)

----- 32编辑-----------

和后续问题--- 放置 const char *定义:: StringN =“Somevalue”

.h文件中的

与将其放在.cpp文件中相比效率低吗?

5 个答案:

答案 0 :(得分:2)

因为这些常量可能与该类紧密耦合。 IE也许该类的成员将这些常量作为参数或返回它们。也许唯一有意义的地方是这个类的接口,所以将它们放在一个单独的命名空间中没有意义,因为它们只对该类有用。

答案 1 :(得分:2)

没有理由按照这里的方式去做;就像没有理由使用class Defines { public: ... };代替struct Defines { ... };一样。也许编写代码的人以前一直在用不支持命名空间中的命名空间/全局变量的语言编写,或者认为这看起来比很多外部语句和命名空间“整洁”。

但是,如果您打算将这些常量中的某些常量设为私有,然后只允许访问少数函数/类,则可以使用它。然而,从它的外观来看,情况并非如此,并且将其更改为命名空间是有意义的 - 这样,可以使用using Defines::constant;和类似的。

对第一次编辑的响应:全局命名空间也是一个命名空间,污染比其他命名空间更危险,因为事情更容易泄漏到它。从这个意义上说,最好将变量放在一个类中,但仍然不如将它们放在自己的命名空间中。

对第二次编辑的响应:标题中的const char* Defines::StringN = "Somevalue";将导致常量被多次定义,并且程序将无法链接。但是,如果你在它之前添加extern,并将定义放在.cpp文件中,那么一切都会没问题,并且应该没有性能损失。

答案 2 :(得分:1)

有几个原因:

  1. 您没有使用可能随机的常量来混淆您的命名空间。
  2. 通过将它们与关联的类包含在一起,您可以为类和常量本身添加含义。
  3. 如果我要定义一个名为NAME的全局/名称空间常量,那么它与之相关联的是什么?如果我添加到类本身,那么你被迫引用类名,这增加了用法的含义,使代码更易读,更不容易出错。

    当然,这可能会被滥用。你可以错放常量。您可以不正确地将真正的全局常量放在特定的类中。在这两种情况下,你都可以提供不好的名字。

答案 3 :(得分:0)

对于大多数事情来说,给它们尽可能小的范围是有意义的。在这种情况下,它不是一个可见性问题,而是清晰度

如果您在方法中看到String1,则无法知道它来自哪里。如果你看到Defines::String1,你可以说“好吧,这是来自班级Defines的一个变量,让我去看看它是什么以及它应该是什么”。查看一个类比查看甚至可能分布在多个源文件中的整个命名空间要好得多。显然,如果变量是在一个类中,因为它主要在该类中使用,那么毫无疑问它就是它应该存在的位置。 :d

答案 4 :(得分:0)

一般来说,没有理由以这种方式使用某种类型。我已经看到它认为如果“常量集合”演变成一个具体的对象,以这种方式开始使转换更容易。在实践中,我从未见过这种情况。它只是隐藏了意图,并且可能会使用私有构造函数来驱散代码。

有人可能会争辩说类可以使用模板,而名称空间则不然。因此,如果Defines是一个类,则以下内容才有效:

template<typename T> int function() {
    return T::x + T::y;
}
//later
cout << function<Defines>() << function<OtherDefines>() << endl;

在大多数情况下,可能会有一个更好的重新设计,特别是如果你所拥有的只是“常量”并非如此。但有时,这可能会派上用场。

有时,它还可以对抗参数依赖查找。简而言之,允许编译器根据传递给函数的参数将其可扩展函数名称扩展到不同的名称命名空间。这不会扩展到类的静态函数。这适用于一般情况,但“静态类”除了包含常量之外还包括嵌套类型和函数。

为什么人们这样做会有所不同。有些来自不能以这种方式使用的语言,有些则不知道更好。