简体   繁体   English

如何在成员函数和非成员函数之间进行选择?

[英]How to choose between member and non-member functions?

Effective C++ says to "Prefer non-member non-frend functions to member functions" (item 23). 有效的C ++表示“将非成员非友好函数优先于成员函数”(项目23)。 The rationale makes sense to me: it minimizes the API "surface area". 基本原理对我来说很有意义:它将API的“表面积”最小化。 But in practice, I often find it hard to convince people (including myself) to follow. 但是实际上,我常常很难说服人们(包括我自己)跟随。 For example, suppose I have some shape classes, and they are supposed to support perimeter and area calculations: 例如,假设我有一些形状类,并且它们应该支持周长和面积计算:

// @interface
class Shape {
 public:
  virtual double Area() = 0;
  virtual double Perimeter() = 0;
}

class Rectangle : public Shape {
 public:
  Rectangle(double width, double height);

  double width();
  double height();

  ...
};

class Circle : public Shape {
 public:
  Circle(double radius);

  double radius();
  ...
};

According to this advice, it seems that Area and Perimeter should be non-member non-friend functions (not methods), because they can be. 根据此建议,似乎Area和Perimeter应该是非成员非友元函数(不是方法),因为它们可以是。 Eg area of a Rectangle can be calculated from the width and height methods like so: 矩形的面积例如可以通过width和height方法来计算,如下所示:

double Area(const Rectangle& rectangle) {
  return rectangle.width() * rectangle.height();
}

In fact, neither Rectangle nor Circle have any internal state that isn't exposed by their getters, and it's hard to imagine how that would ever be the case. 实际上,Rectangle和Circle都没有其吸气剂没有暴露的内部状态,很难想象会发生这种情况。 Therefore, any function that operates on these should not be a method. 因此,对它们进行操作的任何功能都不应该是方法。 Another example: 另一个例子:

// The diameter of a shape is the (circle) diameter of the smallest circle
// that contains a shape.
double Diameter(const Rectangle& rectangle) {
  double w = rectangle.width();
  double h = rectangle.height();
  return sqrt(w * w + h * h);
}

Am I missing something here? 我在这里想念什么吗? Or is this actually bad advice?? 还是这实际上是个坏建议?

If you need to calculate the area of polymorphic Shape objects, then Scott's advice is not for your case. 如果需要计算多态Shape对象的面积,那么Scott的建议不适合您的情况。 Because you cannot calculate the area with an external function, because in fact you don't have public access to the information that is required. 因为您不能使用外部函数来计算面积,所以实际上您没有公共访问所需信息的权限。 Namely, whether the object is actually a circle, a rectangle, or something else. 即,对象实际上是圆形,矩形还是其他形状。 So this is a job for virtual functions. 因此,这是虚拟功能的工作。

In fact, in Scott's psuedo-code algorithm for determining the correct placement of a function (taken from this article , as I do not have the book), the first test is this: 实际上,在Scott的伪代码算法中,用于确定函数的正确位置(摘自本文 ,因为我没有这本书),第一个测试是:

if (f needs to be virtual)
    make f a member function of C;

What do you have if you have a class with some variables that are directly accessible via getters and setters? 如果您有一个包含一些可以通过getter和setter直接访问的变量的类,您将拥有什么? Right, nothing more or less than a struct with an "object oriented" facade. 对了,没有任何多于或少于一个struct具有“面向对象”的门面。 There is absolutely nothing object oriented around the usage of such a data container. 围绕这种数据容器的使用绝对没有面向对象。

The whole point about object orientation, as I percieve it, is to model behaviour , not data . 就我所知,面向对象的全部要点是对行为进行建模,而不是对数据进行建模。 In this respect, an abstract shape class with pure virtual methods to calculate area and perimeter is a perfectly valid design: It abstracts from the data and exposes the behaviour that you need. 在这方面,具有纯虚拟方法来计算面积和周长的抽象形状类是一种完全有效的设计:它从数据中提取出所需的行为。 If I were you, I would think twice about adding the getters for the fundamental parameters (no useful abstraction), and thrice about adding the respective setters (breaks encapsulation). 如果您是我,我会三思而后行为基本参数添加getter(没有有用的抽象),而三思而后行添加各自的setter(破坏封装)。

But, by all means, do not be religious about either having accessors, or not having them, or avoiding simple plain old data structures, or even about an object oriented design. 但是,无论如何,对于拥有访问器或没有访问器,或者避免使用简单的普通旧数据结构,甚至对于面向对象的设计,都不是虔诚的。 All of this has it's uses, and avoiding it for the sake of avoiding it will lead to a poor design in one case or another. 所有这些都有它的用途,而为了避免它而避免使用它会在一种或另一种情况下导致较差的设计。 All I'm saying is: Think about what best suits your needs, and then do it entirely indifferent to what religious rules some big programmers have come up with. 我要说的是:考虑最适合您的需求,然后完全不理会某些大型程序员提出的宗教规则。

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

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