c++ 何时使用命名空间或结构?

cl25kdpy  于 2022-12-05  发布在  其他
关注(0)|答案(7)|浏览(153)

我刚刚从http://www.cplusplus.com/doc/tutorial/namespaces/中阅读了一些关于它们的内容,看起来结构体也能做同样的事情?甚至是类。也许这里有人能更好地定义什么是命名空间,以及它与结构体/类有什么不同?

bfhwhh0e

bfhwhh0e1#

命名空间和类类型的功能是不同的。命名空间主要用于将类型和函数组合在一起以避免名称冲突,而类类型保存数据和对数据进行的操作。
要使用类-类型对函数和对象进行分组,就必须使它们成为静态的:

struct X {
    static void f();
};

如果没有static,你必须创建类类型的示例来使用它们。命名空间更适合这里:

namespace X {
    void f();
}

另一个重要的事情是using声明和指令:

namespace X {
    void f();
    void g();
}

void h() {
    using X::f;
    f(); // f() now visible in current scope
    using namespace X;
    f(); g(); // both visible
}

对于类类型,根本就没有允许这样做的机制。
类类型在命名空间上给予你的是,你可以有多个状态不同的示例--如果你需要的话,可以使用类类型。

yfwxisqw

yfwxisqw2#

好吧,看起来每个人都在努力,所以我会加上我自己的论点。
首先,namespacestruct是完全不同的野兽:它们具有不同语法和不同的语义。
显而易见:

  • a struct引入了一个类型,您可以将其用作模板参数
  • 一个namespace可以分布在多个文件中

语法上:

  • 两者都可以是“别名”,命名空间为namespace ns = mylong::name::space;,结构体为typedef mylong::name::Space lilstruct;
  • ADL(或参数相关查找)是为名称空间量身定制的

语义上:

  • 一个namespace只定义了一个符号定义的作用域,它允许将一起工作的对象(类和自由函数)组合在一起,同时将它们与世界的其他部分隔离(名称冲突)。因此,它通常代表项目中的一个逻辑工作单元(对于小项目,有一个单一的命名空间)。
  • structclass定义了数据和作用于数据的方法之间的逻辑绑定,这是封装的基石。它通常有一个明确的责任和一些不变量。

请注意,有时structclass只是用来将没有任何逻辑的对象绑定在一起,例如struct Person { std::string name, firstName; };
话虽这么说:在C中,使用static方法的struct是没有意义的。这只是对Java或C#及其“纯”面向对象方法的一种曲解。C支持自由函数,所以没有必要不使用它们,特别是因为它更适合封装(它们不能访问私有/受保护的部分,所以你不能弄乱不变式,它们也不依赖于类的表示)。

llycmphe

llycmphe3#

如果可以使用命名空间完成,请使用命名空间。
一个struct不仅仅是定义一个作用域,它还定义了一个类型。

vtwuwzda

vtwuwzda4#

If you don't want people to use the "using" feature of C++ with your class, which can be dangerous and is often ill advised in complex code, then go ahead and use struct with statics.
In other words: if your functions should always be referred to with "group::function", then you can box in your users by declaring as a struct.
In addition, and importantly, you can forward-declare structs in older versions of C++. You cannot do this with namespaces until C++ 11.
Consider:

std::string out zip::pack(const std::string &in)
std::string out zip::unpack(const std::string &in)

In this case, requiring users to specify zip:: makes sense. It's a short, specific and informative. And the names of the underlying functions are ambiguous without it. Use a struct with statics.
Consider:

std::string out CorpDataUtils::zipPack(const std::string &in)
std::string out CorpDataUtils::zipUnpack(const std::string &in)

These should certainly be in a namespace. The namespace name is long, and uninformative, probably more to do with the organization of whoever is maintaining it - which is fine... but really it should be a namespace... not a struct.

x6yk4ghg

x6yk4ghg5#

在C++中,结构体和类是完全一样的,除了结构体默认是公共的。类是私有的。所以无论何时你想把自由函数组合在一起,都要使用命名空间。当你想把数据和函数组合在一起,可以使用结构体/类,也可以选择用命名空间。
注意如果你把你的函数放在一个结构体中,那么当你想调用那些函数时,你必须有一个结构体的示例,除非它们是静态的。

bvuwiixz

bvuwiixz6#

创建自己的库时,通常最好命名所有导出的函数和类。
这样,如果有人包含了您的库,他们就不会污染自己的命名空间,而且发生名称冲突的可能性也会更小。

jecbmhm3

jecbmhm37#

这是一个反例,其中使用struct而不是namespace提供了一些意想不到的好处。
我想把一个二维问题的解推广到K维,这个二维的解包含在一个命名空间中。
我开始改变实现:

struct Point;

template< size_t DIMS >
struct Point;

我需要对大多数类、结构体和函数进行template。这是乏味的、重复的,而且容易出错。然后我有了这个mischevios的想法。我改变了

namespace KDimSpace {

template< size_t DIMS >
  struct KDimSpace {

差不多就是这样了。我可以把里面所有的template< size_t DIMS >垃圾都扯掉。这要容易得多-DIMS的维数只声明一次,并且被所有类型和函数一致地使用。
然后,还有一件事--::detail(子)命名空间后面不是隐藏实现的内部,而是public:private:
有两个烦恼:

  • 函数必须标记为静态
  • 不可能定义运算符(例如,operator<<对应std::ostream),因为运算符不能标记为静态(这样ADL也可能成为障碍)。

底线- C++可能是一种更好的语言,原语更少而不是更多。我希望名称空间像类一样接近结构。

相关问题