首页 \ 问答 \ C ++函数/方法设计的良好实践(Good practice in C++ function/method design)

C ++函数/方法设计的良好实践(Good practice in C++ function/method design)

我对C ++函数/方法设计有如下困惑:

1。

class ArithmeticCalculation
{ 
private:
    float num1_;
    float num2_;
    float sum_;

    void addTwoNumbers();
};

2。

class ArithmeticCalculation
{ 
private:
    float addTwoNumbers(float num1, float num2);
};

在1.中,基本上可以声明一个类变量,而void addTwoNumbers()将实现它并分配给类变量( sum_ )。 我发现使用1.更清洁,但使用2.看起来更直观的功能使用。

考虑到函数/方法,哪一个实际上是最好的选择并不仅限于这个基本的附加功能 - 我的意思是如何决定如何使用return或者仅仅是void?


I have a confusion about C++ function/method design as below:

1.

class ArithmeticCalculation
{ 
private:
    float num1_;
    float num2_;
    float sum_;

    void addTwoNumbers();
};

2.

class ArithmeticCalculation
{ 
private:
    float addTwoNumbers(float num1, float num2);
};

In 1., one can basically declare a class variable and the void addTwoNumbers() will just implement it and assign to the class variable (sum_). I found using 1. is cleaner but using 2. looks like it more intuitive for function use.

Which one is actually best option considering the function/method is not restricted to only this basic addition functionality -- I mean in general how to decide to use with return or simply void?


原文:https://stackoverflow.com/questions/47420381
更新时间:2019-07-15 05:16

最满意答案

这两个函数的主要区别在于第二个函数是无状态* ,而第一个函数有一个状态。 在其他条件相同的情况下,无状态方法更受欢迎,因为它可以让您班级的用户在系统中利用您的班级时更加灵活。 例如,无状态函数是可重入的,而依赖于状态的函数可能需要使用它们的代码采取额外措施来防止错误使用。

只要可能,重新进入就是选择无状态函数的一个重要原因。 但是,在保持状态变得更经济的情况下 - 例如,当您使用Builder Design Pattern时

保持函数无状态的另一个重要优点是,调用序列变得更具可读性。 依赖于状态的方法调用由以下部分组成:

  • 在通话之前设置对象
  • 拨打电话
  • 收获通话结果(可选)

您的代码的人类阅读者读取使用带有参数传递的函数调用的调用比读取三部分的调用 - 获取结果序列更容易。

有些情况下,你必须有状态,例如,当你想推迟行动时。 在这种情况下,参数由代码的一部分提供,而计算由代码的其他部分启动。 就你的例子而言,一个函数会调用set_num1set_num2 ,而另一个函数稍后会调用addTwoNumbers 。 在这种情况下,您可以将参数保存在对象本身上,或使用延迟参数创建单独的对象。

*这只是基于您的成员函数签名的假设。 你的第二个函数获取它需要的所有数据作为参数,并将值返回给调用者; 显然,实现可以选择添加一些状态,例如通过保存最后的结果,但addTwoNumbers函数不常见,所以我假设你的代码不会这样做。


The major difference between the two functions is that the second one is stateless*, while the first one has a state. Other things being equal, stateless approach is preferred, because it gives the users of your class more flexibility at utilizing your class in their systems. For example, stateless functions are re-entrant, while functions that rely on state may require the code that uses them to take additional measures that prevent incorrect use.

Re-entrancy alone is a big reason to prefer stateless functions whenever possible. However, there are situations when keeping state becomes more economical - for example, when you are using Builder Design Pattern.

Another important advantage of keeping your functions stateless whenever it is possible is that the call sequence becomes more readable. A call of a method that relies on the state consists of these parts:

  • Set up the object before the call
  • Make the call
  • Harvest the result of the call (optional)

Human readers of your code will have much easier time reading the call that uses a function invocation with parameter passing than the three-part setup-call-get result sequence.

There are situations when you have to have state, for example, when you want to defer the action. In this case the parameters are supplied by one part of the code, while the computation is initiated by some other part of the code. In terms of your example, one function would call set_num1 and set_num2, while another function would call addTwoNumbers at some later time. In situations like this you could save the parameters on the object itself, or create a separate object with deferred parameters.

* This is only an assumption based on the signature of your member function. Your second function gets all the data that it needs as parameters, and returns the value to the caller; Obviously, implementations may choose to add some state, e.g. by saving the last result, but that is uncommon for addTwoNumbers functions, so I assume that your code does not do it.

2017-11-21

相关文章

更多

最新问答

更多
  • 删除不适用于JSP中使用for循环的每个id(Deletion not working for every id using for loop in JSP)
  • 如何从std :: filesystem :: path中删除引号(How to remove quotation marks from std::filesystem::path)
  • 验证多个控制器方法的URL路径(Validate URL path for several controller methods)
  • 如何在datarow []中的列中找到最大值?(How to find max value in a column in a datarow[] ?)
  • 如何使用预定义文本替换来自数据库的部分结果(How do I replace part of result coming from Database with predefined text)
  • Selenium Java注入了新的Javascript函数(Selenium Java inject new Javascript function)
  • 使用.on的多个下拉菜单选择文本仅适用于第一个下拉列表(Multiple Dropdowns Menu Selection text using .on works only on first dropdown)
  • 快速将黄土曲线添加到大型数据集图中的方法(Quick way to add loess curve to large data set graph)
  • FilteringSelect in mvc(FilteringSelect in mvc)
  • 在Delphi XE2中开发Mac或iOS应用程序需要哪些硬件/软件?(What hardware/software is necessary to develop Mac or iOS apps in Delphi XE2?)
  • 在原型的构造函数中初始化属性时获取“未定义”(Getting 'undefined' when a property is initialized in the constructor of a prototype)
  • 通过越狱加载的应用程序的Documents文件夹位置(Location of Documents folder for an app loaded via jailbreak)
  • 在OpenGL中使用可编程和固定管道功能(Using both programmable and fixed pipeline functionality in OpenGL)
  • 将任何用户输入重定向到单独的底层程序(redirect any user input to a separate underlying program)
  • 编辑文本不能正常工作android(Edit texts not working properly android)
  • “user_denied”Facebook应用页面上的Facebook用户区域设置(Facebook user locale on “user_denied” facebook app page)
  • 在大图像中找到小的部分透明图像的坐标(find coordinates of small partially-transparent image within a large image)
  • 我如何在cakephp 3.1中获得完整的相对路径?(How i can get full relative path of image in cakephp 3.1?)
  • 如何保存拖动标记的新本地化?(How to save new localization of dragged marker?)
  • MySQL UPDATE vs INSERT和DELETE(MySQL UPDATE vs INSERT and DELETE)
  • 在执行查询之前,在SQLAlchemy模型中将datetime转换为unix时间戳?(Convert datetime to unix timestamp in SQLAlchemy model before executing query?)
  • OpenCL与OpenGL互操作的优势(Advantage of OpenCL interoperability with OpenGL)
  • 如何解析用点和等分隔的数据然后添加到listview(How to parsing data from delimited with dot and equal then add to listview)
  • 带调试输出的X3解析器段错误(BOOST_SPIRIT_X3_DEBUG)(X3 parser segfaults with debug output (BOOST_SPIRIT_X3_DEBUG))
  • 将文件夹名称添加到fgrep结果(Add folder name to fgrep result)
  • 在MySQL中加载一个表是非常慢的(Loading one table in MySQL is ridiculously slow)
  • 如何将JSON放入PHP变量?(How do I put JSON into a PHP Variable?)
  • 如何绕过Microsoft.Speech.Recognition中的不流畅?(How to bypass disfluencies in Microsoft.Speech.Recognition?)
  • 原点的最后一行是什么?(What is the last row of an origin for?)
  • 将字符串转换为javascript中的操作(Translate String to operation in javascript)