【问题标题】:Class member vs function argument类成员与函数参数
【发布时间】:2013-06-20 10:25:28
【问题描述】:

我有一个关于如何使用 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();

也可以设计一个没有variable1variable2 的类。

    class MyClass
    {
    public:

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

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

【问题讨论】:

  • 在设计一个类(一个类型)时,总是问自己一个问题:MyClass 有这样的属性或属性吗?

标签: java c++ class


【解决方案1】:

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

【讨论】:

    【解决方案2】:

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

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

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

    【讨论】:

      【解决方案3】:

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

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

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

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

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

      【讨论】:

        【解决方案4】:

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

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

        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;
        };
        

        【讨论】:

          【解决方案5】:

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

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

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

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

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2019-10-16
            • 1970-01-01
            • 1970-01-01
            • 2015-02-26
            • 1970-01-01
            • 2015-01-15
            • 1970-01-01
            相关资源
            最近更新 更多