类成员vs函数参数
Class member vs function argument
我有一个关于如何使用面向对象语言(如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();
也可以设计一个没有variable1
和variable2
的类。
class MyClass
{
public:
bool perform_one_task(int variabl1, int variable2)
{
// do something
return true;
}
}
在这个类中,variable1
和variable2
不是类的成员,而是函数的参数。我的问题是在哪种情况下第一种设计策略更可取,哪种情况下第二种设计模式更好。给出的例子只假设variable1
和variable2
的结构很小,但是如果它们很大,例如,variable1
可能是一个大的数据数组。
当你需要在类实例生命周期的其他地方使用值时,你应该使用第一种模式(成员);否则,如果你只需要在方法中使用值,你应该使用第二种模式
第一个示例是面向对象的(假设perform_one_task()
使用了这些变量!)。第二个例子不是,它只是一个用空类包装器包装的函数。
一般来说,面向对象类是打包一些数据和所有相关操作(方法)的一种方式。类在建模真实世界的对象或概念时效果最好。封装在类中的数据受到保护,只能由类提供的操作访问或操作。你通常希望一个类有几个方法以不同的方式操作相同的数据,所以你的例子有点太简单了。
如果您尝试在示例中添加另一个任务,那么您将看到,在第二个示例中,您将最终得到两个不相关的函数,而在第一个示例中,每个任务都能够操作相同的数据。
类实际建模是什么?什么需要封装?谁真正拥有这些数据?
在第一个示例中,成员是实现细节。它们对类的用户/客户端是隐藏的,您可以替换它们并完全更改实现。perform_one_task()
方法的客户端不知道这些字段的存在。
。类可以表示二维坐标,成员可以表示X/Y属性。在某些阶段,您可以更改该类以极坐标形式(角度+半径)表示坐标。坐标类的API将保持不变,但实现将从根本上不同。
第二个值纯粹是封装功能。类可以不使用它自己拥有的数据来表示。这并非不合理。您可以合法地实现(例如)一个Calculator
类,它只执行计算并封装该功能。将它放在类中的好处是它实现了一些可重用性,并且不受原始源代码的约束。
底线是,你可以编写获取/保存/拥有数据的类,也可以编写不保存状态的类。这两种方法在不同的场景中都是合理的。最根本的问题仍然是谁拥有/控制这些数据。
类成员就是类成员。这些是类对象实例的属性或整个类使用的静态值——因此与类密切相关的值。
你不会在你的类中存储那些不能为你的类建模的值,除非你需要它们(然后它们实际上为你的类建模)。这是不必要的,浪费资源。总是避免不必要的变量。所以基本上: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;
};
根据面向对象编程(OOP)的原则,当你开发你的类时,你通常选择什么是对象属性(状态),什么是对象方法(行为)。在这里,方法可以有输入参数。因此,我们可以将您的问题改写为:对象属性和方法参数之间的区别是什么。
对象属性是表征该对象的属性(状态特征),例如3D点由3个坐标表征:x, y, z;圆的特征是中心坐标和半径。
对象方法(行为)是应用于该对象的计算,例如三角形可以有这样的方法,如calculateSquare(), calculatePerimeter(), rotate(angle), move(newX, newY)等
最后方法参数是该方法的输入数据,但它们不是对象属性。例如,2D形状对象可以有rotate(angle)方法,其中angle不是形状对象的属性,而是rotate方法的输入参数,即旋转形状的角度。
- 将可变参数函数的参数封装在类实例中
- QML 使用带有参数C++函数
- 使用可变参数函数作为模板参数
- 如何在C++中伪造虚拟可变参数函数模板?
- 为什么可变参数函数不适用于模板
- C++ std::functional 中的可变参数函数模板
- 可变参数函数指针的定义对于VxWorks spyLib来说不清楚
- 使用可变参数函数覆盖具有不同函数签名的虚函数
- 考虑引用和常量的可变参数函数包装器
- 使用可变参数函数将整数和/或整数数组放入单个 int 数组中
- 在可变参数函数中转发特定范围的参数
- 通过引用传递参数;函数返回类型是否必须为 VOID?
- 使用带有一个参数函数的递归找到数字的平方
- 可变参数函数模板不能很好地使用 std::function 作为参数
- 多个可变参数函数的单个模板参数包?
- 参数数据类型未知的可变参数函数
- 可变参数函数参数包扩展
- 使用模板可变参数函数将多个参数传递给另一个函数
- 对可变参数函数的递归调用的链接器错误
- 通过像printf这样的可变参数函数传递一个带有常量字符*转换函数的类