29

将命名空间用作静态类是好的还是好的做法?例如:

namespace MyStaticFunctions {
    void doSomething();
}

相对:

class MyStaticFunctions {
    static void doSomething();
}
4

4 回答 4

34

C++ 中没有“静态类”之类的东西,所以从 C++ 的角度来看,您不是在“作为静态类”使用它,而是在“作为命名空间”使用它。使用命名空间将函数组合在一起当然是公认的做法。

但是,您希望这些组有多大,这取决于您。C++ 库为整个公共接口使用单个命名空间并不罕见。对于习惯于(比如)Java 的人来说,这可能会让他们感到惊讶,因为在 Java 中,类通常用于将较少数量的静态方法组合在一起。由于 C++ 最先出现,您可以说 Java 使用类作为命名空间。

因此,在 C++ 中,您不会看到类似于java.util.Collectionsor的类java.lang.Math充满静态成员。如果您想要 C++ 中的函数组,请使用命名空间。

例外(C++ 中不是总是有特殊情况吗?)是特征类型,例如std::numeric_limits<T>,其中模板参数使类执行命名空间无法执行的操作。您可以定义一个numeric_limits包含函数模板max<T>()等的命名空间min<T>(),但它不是那么好。首先,它对事物的分组略有不同,类型T显示为“层次较低”。其次,它并没有做特征类型所做的所有事情,因为没有“对象模板”之类的东西可以让你定义一个值numeric_limits::digits<T>

我不太了解 C# 来评论静态类的实际用途,但 AFAIK 它只是一个限制为没有非静态成员的类,所以它类似于那些 Java 类。

于 2013-01-16T15:11:59.047 回答
22

在 C++ 中,实际上鼓励您在语言级别使用 anamespace而不是class仅包含a 的static方法,因为 Koenig 的查找(也称为 Argument Dependent Lookup)。

例子:

namespace geometry {
    struct Point { int x, y; };

    double distance_from_center(Point const& p) {
        return sqrt(p.x * p.x + p.y + p.y);
    }
} // namespace geometry

int main() {
    geometry::Point const p{3, 4}; // must qualify

    std::cout << distance_from_center(p) << "\n"; // not qualified
}

如果distance_from_center被写为 astatic中的方法class,那么您每次都需要明确限定它。

于 2013-01-16T15:22:12.063 回答
8

对我个人来说,这是一个棘手而有趣的问题,所以决定分享我的拙见

考虑“静态”类(仅静态成员)和命名空间之间的区别:

  1. 命名空间可以分散在多个文件中:额外的灵活性,但应谨慎使用。
  2. 命名空间提供依赖于参数的查找(参见 Matthieu M. answer):在特定情况下很有用
  3. “静态”类可以具有访问修饰符并可以形成层次结构:我认为在类接口中声明且对其客户端可见的私有成员是 C++ 特性,它更多地是由技术而非逻辑原因决定的。我看不到私有静态成员的任何好处。“静态”层次结构的受保护成员?从来没有见过。
  4. 除了模板成员之外,“静态”类可以是“模板”:请参阅Steve Jessop 的回答,了解 STL 中的一个很好的示例

从维护的角度来看,有时您决定将一个类设为“静态”(如单例),但随后需求发生了变化,您需要多个实例。“静态”类比命名空间更容易转换。

最后,回答你的问题:

如果您不需要“静态”类或命名空间的特殊功能,请使用您更喜欢的功能:)

于 2013-01-16T15:51:59.947 回答
4

这取决于。

该方法在逻辑上是否与类相关?如果是,则使其成为成员,否则将其放置在命名空间中。

从功能上讲,它们是相同的,但代码比功能更多,对吧?例如,考虑一个返回类名的方法:

struct MyClass
{
    static std::string getName() { return "MyClass"; }
}

您显然可以将该方法放在 a 之外namespace,并获得相同的结果,但它在逻辑上属于该类。

于 2013-01-16T15:08:24.587 回答