简体   繁体   English

何时使用名称空间或结构?

[英]When to use a namespace or a struct?

I was just reading a little bit on them from http://www.cplusplus.com/doc/tutorial/namespaces/ and it seems like a struct is capable of the same things?我只是从http://www.cplusplus.com/doc/tutorial/namespaces/读了一些关于它们的内容,似乎结构也能做同样的事情? Or even a class for that matter.或者甚至是 class。 Maybe someone here can better define what a namespace is, and how it differs from a struct/class?也许这里有人可以更好地定义命名空间是什么,以及它与结构/类有何不同?

Namespaces and class-types are not capable of the same things. 命名空间和类类型不具备相同的功能。 Namespaces are mainly used to group types and functions together to avoid name collisions, while class-types hold data and operations that work on that data. 命名空间主要用于将类型和函数组合在一起以避免名称冲突,而类类型包含处理该数据的数据和操作。

To just group functions and objects by using a class-types you'd have to make them static: 要使用类类型对函数和对象进行分组,您必须将它们设置为静态:

struct X {
    static void f();
};

Without static you'd have to create instances of the class-types to use them. 如果没有static您必须创建类类型的实例才能使用它们。 A namespace is much better suited here: 命名空间在这里更适合:

namespace X {
    void f();
}

Another important thing are using declarations and directives: 另一个重要的事情是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
}

With class-types there simply is no mechanism that allows that. 对于类类型,根本没有允许这种情况的机制。

What class-types give you over namespaces is that you can have multiple instances with differing state - if you need that use a class-type. 什么类类型为您提供了名称空间,您可以拥有多个具有不同状态的实例 - 如果您需要使用类类型。

Well, seems everyone's going at it, so I'll add my own arguments. 好吧,似乎每个人都在努力,所以我会添加自己的论点。

First things first, namespace and struct are completely different beasts: they have different syntax and different semantics. 首先, namespacestruct是完全不同的野兽:它们具有不同的语法和不同的语义。

The obvious: 显而易见的:

  • a struct introduces a type, you can use as templates argument struct引入了一个类型,可以用作模板参数
  • a namespace can be spread in several files namespace可以分布在多个文件中

Syntactically: 在语法:

  • both can be "aliased", namespace with namespace ns = mylong::name::space; 两者都可以是“别名”,名称空间为namespace ns = mylong::name::space; and struct with typedef mylong::name::Space lilstruct; 和struct with typedef mylong::name::Space lilstruct;
  • ADL (or Argument Dependent Lookup) is tailored for namespaces ADL(或Argument Dependent Lookup)是为命名空间量身定制的

Semantically: 语义:

  • a namespace only defines a scope for the definition of symbols, which allows to group together objects that work together (classes and free-functions) while isolating them for the rest of the world (name clashes). namespace只定义符号定义的范围,它允许将一起工作的对象(类和自由函数)组合在一起,同时将它们隔离到世界其他地方(名称冲突)。 As such it often represents a logical unit of work within the project (for small projects, there is a single namespace). 因此,它通常代表项目中的逻辑工作单元(对于小项目,只有一个命名空间)。
  • a struct or class defines a logical binding between data and the methods to act upon it, which is the corner stone of encapsulation. structclass定义数据和作用于它的方法之间的逻辑绑定,这是封装的基石。 It usually has one clear responsability and a number of invariants. 它通常有一个明确的责任和一些不变量。

Note that sometimes a struct or class is just used to bind together objects that work together without having any logic, for example struct Person { std::string name, firstName; }; 请注意,有时structclass仅用于将没有任何逻辑的对象绑定在一起,例如struct Person { std::string name, firstName; }; struct Person { std::string name, firstName; }; .

That being said: there is no point in C++ for a struct of static methods. 话虽如此:C ++中没有关于static方法struct的观点。 It's just a perversion from Java or C# and their "pure" OO approach. 这只是来自Java或C#的反转以及他们的“纯粹”OO方法。 C++ supports free functions, so there is no point not using them, especially since it's better for encapsulation (they don't have access to private/protected parts, so you can't mess up an invariant and they don't depend on the representation of the class either). C ++支持自由函数,所以没有必要不使用它们,特别是因为它更适合封装(它们无法访问私有/受保护的部分,所以你不能搞乱一个不变量而且它们不依赖于该类的代表)。

When creating your own library, it's normally good practice to namespace all your exported functions and classes. 在创建自己的库时,通常最好将所有导出的函数和类命名为。

That way, if someone includes your library, they won't be polluting their namespace, and there is less likelyhood of name clashes. 这样,如果有人包含您的库,他们将不会污染他们的名称空间,并且名称冲突的可能性更小。

If it can be done with a namespace, use a namespace. 如果可以使用命名空间完成,请使用命名空间。

A struct does much more than defining a scope. 结构不仅仅是定义范围。 It defines a type. 它定义了一种类型。

In C++ a struct is exactly the same as a class, except structs are public by default. 在C ++中,结构与类完全相同,但默认情况下结构是公共的。 Classes are private. 课程是私人的。 So whenever you want to group free functions together use a namespace. 因此,只要您想要将自由函数组合在一起,就可以使用命 When you want to group data and functions, use a struct/class, and optionally a namespace around it all. 如果要对数据和函数进行分组,请使用结构/类,并可选择围绕它使用命名空间。
Notice that If you put your functions in a struct then you would have to have an instance of your struct when you want to call those functions, unless they are static. 请注意,如果将函数放在结构中,那么当您想要调用这些函数时,您必须拥有结构的实例,除非它们是静态的。

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. 如果你不希望人们在你的类中使用C ++的“使用”功能,这可能是危险的,并且在复杂的代码中经常被告知,那么继续使用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. 换句话说:如果你的函数应该总是用“group :: function”引用,那么你可以通过声明为结构来装入你的用户。

In addition, and importantly, you can forward-declare structs in older versions of C++. 此外,重要的是,您可以在旧版本的C ++中转发声明结构。 You cannot do this with namespaces until C++ 11. 在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. 在这种情况下,要求用户指定zip ::是有意义的。 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. 命名空间名称很长,而且没有信息,可能更多地与维护它的人的组织有关 - 这很好......但实际上它应该是命名空间...而不是结构。

This is a counter example where using a struct instead of a namespace gives some unexpected benefits.这是一个反例,其中使用struct而不是namespace会带来一些意想不到的好处。

I wanted to generalise a solution to a 2D problem to K dimensions.我想将二维问题的解决方案概括为 K 维。 The 2D solution was enclosed in a namespace.二维解决方案包含在命名空间中。

Templates to the rescue.模板来拯救。 I started changing the implementation:我开始改变实现:

struct Point;

to

template< size_t DIMS >
struct Point;

I needed to template most classes, structs, and functions.我需要对大多数类、结构和函数进行template化。 That was tedious, repetitive, and error prone.那是乏味的、重复的,而且容易出错。 And then I had this mischevios idea.然后我有了这个恶作剧的想法。 I changed我变了

  namespace KDimSpace {

to

  template< size_t DIMS >
  struct KDimSpace {

and that was pretty much it.仅此而已。 I could rip off all template< size_t DIMS > junk inside.我可以撕掉里面所有的template< size_t DIMS >垃圾。 This is so much easier - the number of dimensions DIMS is declared only once and used consistently by all types and functions.这要容易得多——维数DIMS只声明一次,并被所有类型和函数一致使用。

And then, there is one more thing - rather than hiding internals of the implementation behind ::detail (sub)namespace there is public: and private: !然后,还有一件事 - 而不是将实现的内部隐藏在::detail (sub)namespace 后面,而是public:private:

There are two annoyances:有两个烦恼:

  • functions have to be marked as static函数必须标记为 static
  • it is not possible to define operators (eg operator<< for std::ostream ) because operators cannot be marked as static (and then ADL might get in the way as well).无法定义运算符(例如operator<<用于std::ostream ),因为运算符不能标记为 static(然后 ADL 也可能会妨碍)。

Bottom line - C++ could be a better language with fewer primitives not more.底线 - C++ 可能是一种更好的语言,原语更少而不是更多。 I would like namespaces to be as close to structs as classes are.我希望名称空间与类一样接近结构。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM