简体   繁体   English

Scott Meyers建议偏爱非成员非朋友方法是否适用于对象构建?

[英]Does Scott Meyers's advice to prefer non-member non-friend methods apply to object construction?

Let's say I have a class: 假设我有一节课:

class C{
  int x_;
  int y_;
public:
  C(int x, int y): x_(x), y_(y){}
};

Then I want to add construction from a string, which would just parse x and y . 然后我想从一个字符串添加构造,它只会解析xy Before reading Meyers's book I would usually make it another constructor in class C . 在阅读迈耶斯的书之前,我通常会将它作为C另一个构造函数。 However, it's also possible to make it non-member non-friend: 但是,它也可以使其成为非会员非朋友:

C CFromString(const std::string& s){
  int x, y;
  //...parse them somehow, throw exception if needed...
  return C(x,y);
}

To me this is standard situation for many "value classes", when there is a "main" constructor which sets private members to provided values (probably checking there correctness). 对我来说,这是许多“值类”的标准情况,当有一个“主”构造函数将私有成员设置为提供的值(可能检查正确性)。 Other constructors for such classes are often just calculate these values from some other arguments. 这些类的其他构造函数通常只是从其他一些参数计算这些值。

Are there any drawbacks in making such constructors non-member non-friends like in my example? 在我的例子中,使这样的构造函数成为非成员非朋友有什么缺点吗?

Upd. UPD。 I understand the Meyers's advice, and what are the advantages of NMNF functions. 我理解Meyers的建议,以及NMNF功能的优点。 There is just no examples of NMNF object construction in his book, so I want to ensure that his advice applies to construction as well. 在他的书中没有关于NMNF对象构造的例子,所以我想确保他的建议也适用于建筑。

If you start adding constructors for every possible way a class can be serialized, you are tightly coupling that class with those serialization methods. 如果您开始为每个可能的方式添加构造函数,可以序列化类,那么您将该类与这些序列化方法紧密耦合。

It is preferred that you separate the class and the serializer in order to separate concerns. 您最好将类和序列化程序分开以分离关注点。 Let the class focus on what the class does and the serializer on what it does (read json or whatever) 让课程专注于课程的作用和序列化器的作用(阅读json或其他)

You have to consider that your class might be serialized from a file, from a socket, from json, from xml, from a database...from any number of things. 您必须考虑您的类可能是从文件,套接字,json,xml,数据库......来自任意数量的序列化。

That's why in modern programming we use interfaces. 这就是为什么在现代编程中我们使用接口。 We also make use of the Factory pattern. 我们还使用了Factory模式。

One drawback is a bit of inconsistency, which is an esthetic concern. 一个缺点是有点不一致,这是一个美学问题。

You're calling a CFromString constructor function rather than invoking a constructor called C . 您正在调用CFromString构造函数而不是调用名为C构造函数。 The relationship between them is arbitrary, just through the C prefix in the name. 它们之间的关系是任意的,只需通过名称中的C前缀即可。

If you make it a static member function, then you can call it C::FromString so that it belongs to the class. 如果你使它成为一个static成员函数,那么你可以将其称为C::FromString以便它属于该类。

If this is done all over the place in a large project, some sort of convention would help. 如果在大型项目中的所有地方都这样做,那么某种约定会有所帮助。 Like say, whenever we have a class C , and a non-member constructor function for making C -s, let's always call it CCons , and then always use overloading for different types. 比如说,每当我们有一个C类和一个非成员构造函数来制作C -s时,让我们总是把它CCons ,然后总是使用重载来处理不同的类型。 Thus, if we have a Widget class, we then call our overloaded family WidgetCons : 因此,如果我们有一个Widget类,那么我们调用我们的重载族WidgetCons

Widget WidgetCons(const std::string &s) { /* make it from string */ }
Widget WidgetCons(int i) { /* make it from int */ }

and so on. 等等。 If this is consistent in our 250,000 line codebase, whenever someone sees any FooCons or BarCons , they know exactly what it is. 如果这在我们的250,000行代码库中是一致的,那么只要有人看到任何FooConsBarCons ,他们就会确切地知道它是什么。

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

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