3

我有一个关于如何使用面向对象语言(如 c++)设计类的问题。在许多情况下,变量既可以分配给类成员,也可以分配给函数参数。我举以下例子来说明我的观点:

class MyClass
{
public:
  int variable1;
  int variable2:
  MyClass (int vr1, int vr2)
  {
     variable1 = vr1;
     variable2 = vr2;
   }
  bool perform_one_task()
  {
    // do something
    return true;
  }
}

当我们要使用这个类时,可以使用如下代码:

  int a,b;
  MyClass mine(a,b);
  mine.perform_one_task();

也可以设计一个没有variable1and的类variable2

    class MyClass
    {
    public:

      bool perform_one_task(int variabl1, int variable2)
      {
        // do something
        return true;
      }
    }

在这个类variable1variable2并不是类的成员而是成为函数的参数。我的问题是第一种设计策略在哪种情况下更可取,第二种设计模式在哪种情况下更好。给定的示例仅假设 和 的结构variable1很小variable2,但如果它们很大,例如,variable1可能是一个大型数据数组。

4

5 回答 5

0

根据面向对象编程 ( OOP ) 的原则,当您开发您的类时,您通常会选择什么是对象属性(状态)和什么是对象方法(行为)。这里方法可以有输入参数。因此,我们可以将您的问题改写为:对象属性和方法参数之间的区别是什么。

对象属性是其表征该对象的属性(状态特征),例如 3D 点由 3 个坐标表征:x、y、z;圆的特点是中心坐标和半径。

对象方法(行为)是应用于该对象的计算,例如三角形可以有calculateSquare()、calculatePerimeter()、rotate(angle)、move(newX, newY)等方法。

最后,方法参数是该方法的输入数据,但它们不是对象属性。例如,2D 形状对象可以有方法 rotate(angle),其中角度不是形状对象的属性,而是旋转方法的输入参数,即旋转形状的角度。

于 2013-06-20T11:08:01.460 回答
0

您的第一个示例是面向对象的(假设perform_one_task()使用变量!)。您的第二个示例不是,它只是一个包装在空类包装器中的函数。

一般来说,面向对象的类是打包一些数据和所有相关操作(方法)的一种方式。类在模拟一些现实世界的对象或概念时效果最好。封装在类中的数据受到保护,只能通过类提供的操作来访问或操作。您通常希望一个类有多个方法以不同的方式对相同的数据进行操作,因此您的示例有点太简单了。

如果您尝试在示例中添加另一个任务,那么您会看到在第二个示例中您最终会得到两个不相关的函数,而在第一个示例中,每个任务都能够操作相同的数据。

于 2013-06-20T11:10:05.740 回答
0

类成员是类成员。这些是类对象实例的属性或整个类使用的静态值 - 因此值与类密切相关。

除非您需要它们(然后它们实际上为您的类建模),否则您不会在您的类中存储不为您的类建模的值。这是不必要的,也是资源的浪费。始终避免不必要的变量。所以基本上:

class MyClass{
public:
  bool perform_one_task(int onlyMethodArg1, int onlyMethodArg2){
    // do something
    return true;
    // onlyMethodArgs are gone since nobody really needs them, we are interested 
    // only in result of calculation
  }
void saveProperties(int prop1, prop2){
    property1=prop1;
    property2=prop2;
} 
private:
    int property1;
    int property2;
};
于 2013-06-20T11:14:10.850 回答
0

什么是类实际上建模?需要封装什么?谁真正拥有这些数据?

在您的第一个示例中,成员是实现细节。它们对类的用户/客户隐藏,您可以替换它们并完全更改实现。该方法的客户perform_one_task()不知道这些字段的存在。

例如,您的类可以表示二维坐标,您的成员可以表示 X/Y 属性。在某个阶段,您可以更改该类以用极坐标表示坐标(角度+半径)。坐标类的 API 将保持不变,但实现将根本不同。

您的第二个价值纯粹是封装功能。该类可以用它本身拥有的任何数据来表示。这并非没有道理。您可以合法地实现(比如说)一个Calculator简单地执行计算并封装该功能的类。将它放在一个类中的好处是它实现了一些可重用性并且不依赖于原始源代码。

底线是您可以编写获取/持有/拥有数据的类,以及不持有状态的类。这两种方法在不同的情况下都是合法的。基本问题仍然是谁拥有/控制该数据。

于 2013-06-20T10:28:39.617 回答
0

当你需要在类实例生命周期的其他地方使用值时,你应该使用第一个模式(成员):否则,如果你只需要在方法中使用值,你应该使用第二个模式

于 2013-06-20T10:29:04.187 回答