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

时间:2017-03-29 22:05:25

标签: c++ constructor

假设我有一个班级:

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

然后我想从一个字符串中添加构造,它只会解析xy。在阅读Meyers的书之前,我通常会在课程C中将其作为另一个构造函数。但是,它也可以使其成为非成员非朋友:

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

对我来说,这是许多“值类”的标准情况,当有一个“主”构造函数将私有成员设置为提供的值(可能检查正确性)。这些类的其他构造函数通常只是从其他一些参数中计算出这些值。

在我的例子中,使这样的构造函数成为非成员非朋友有什么缺点吗?

更新。我理解Meyers的建议,以及NMNF功能的优势。他的书中没有关于NMNF对象构造的例子,所以我想确保他的建议也适用于建筑。

2 个答案:

答案 0 :(得分:5)

如果您开始为每个可能的方式添加构造函数,可以序列化类,那么您将该类与这些序列化方法紧密耦合。

最好将类和序列化程序分开以分离关注点。让课程关注课程的作用以及序列化器的作用(阅读json或其他)

你必须考虑你的类可能是从一个文件,一个套接字,一个json,一个xml,一个数据库......从任意数量的东西中序列化的。

这就是为什么在现代编程中我们使用接口。 我们还使用了工厂模式。

答案 1 :(得分:3)

一个缺点是有点不一致,这是一个美学问题。

您正在调用CFromString构造函数,而不是调用名为C的构造函数。它们之间的关系是任意的,只需通过名称中的C前缀。

如果你使它成为static成员函数,那么你可以将其称为C::FromString,使其属于该类。

如果在大型项目中的所有地方都这样做,某种约定会有所帮助。比如说,每当我们有一个类C,以及一个用于创建C - s的非成员构造函数时,我们总是将其称为CCons,然后始终使用重载适用于不同类型。因此,如果我们有一个Widget类,我们就会调用我们的重载家庭WidgetCons

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

等等。如果这在我们的250,000行代码库中是一致的,那么只要有人看到任何FooConsBarCons,他们就会确切知道它是什么。