首页 \ 问答 \ 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

相关问答

更多

Wordpress菜单样式(Wordpress menu style)

不要对列表项使用填充。 您还需要将锚标记的属性值显示为内联块或块。 display:inline-block; /* Or just */ display:block; 请参阅下面的chnages nav li { background-color: #99D9F3; margin-bottom: 2px; padding: 0; font-weight: 300; } nav a { color: #000; mar

创建对象会产生意外结果(creating an object gives unexpected results)

你的问题是object需要大写 - object不是JavaScript中的东西,而是Object 。 你要: var car=new Object(); 正如w3schools所说 ,JavaScript标识符区分大小写: 所有JavaScript标识符都区分大小写。 变量lastName和lastname是两个不同的变量。 所以object和Object是两个不同的东西,你想要Object - JS中的几乎所有东西都是以Object开头的。 更多关于对象的信息 。 此外,正如car.spe

在尝试使用JFugue进行解析时,Musixml解析异常,如何解决这个问题?(Musixml parsing exception when trying to parse with JFugue, how to fix this?)

我没有从musicxml官方网站获取dtd文件的解决方法是在本地引用它,这样你就不需要网络连接来读取musicxml文件了。 如: <!DOCTYPE score-partwise PUBLIC "-//Recordare//DTD MusicXML 2.0 Partwise//EN" "../musicxmldtd/partwise.dtd"> A workaround I used for not getting the dtd files from the musicxml offici

处理Java中重写接口中的异常(Dealing with Exception in Overridden Interface in Java)

有一种方法可以使用构造函数引用实例化一个没有异常的类。 例如: Supplier<SomeType> eCons = SomeType::new; Supplier用于默认构造函数,但您可以使用与要引用的构造函数的签名匹配的任何功能接口类型(例如,此处列出的其中一个: 链接 )(例如,带参数的构造函数)。 对于Supplier ,您可以调用get()来创建新实例: EdgeProvider<V, E> ep = new EdgeProvider<V, E>() { @Override

嘲笑斯威夫特(Mocking with Swift)

所以,你想测试一个方法( foo )是否调用另一个方法( bar )。 foo方法是被测试的方法,而bar方法在更广泛的意义上是依赖组件。 如果调用bar具有持久的副作用,您可以通过查询属性或类似物来测试副作用是否存在。 在这种情况下,你不需要嘲笑或类似。 如果没有副作用,那么你必须替换依赖。 为此,您需要一个接缝 ,您可以在其中放置可以告诉测试该方法是否已被调用的代码。 为此,我只能看到Jon在您提到的问题中已经讨论过的两个选项。 您可以将两个方法放在单独的类中,在这种情况下,类边界是接缝。

根据不同的媒体查询更改内容(changing content depending on different media queries)

您可以使用边距或文本缩进属性将内容方式突出显示在屏幕显示区域之外,从而创建隐藏效果。 这些方法不是我称之为100%干净的方法,但它们至少使您的HTML标记保持整洁。 查看这个有用的线程 ,解释屏幕阅读器与CSS隐藏元素的交互。 我还假设你的CSS中的第二个引用是指--changer not --charger 。 另外,如果语句: .main__header--changer {display: none;}在所有媒体查询中都是相同的,那么您应该考虑在任何查询之外编写一次,这样它就可以普遍应用而

验证ISO8601 start_time在elixir / ecto / timex中的ISO8601 end_time之前(Validate ISO8601 start_time is before ISO8601 end_time in elixir/ecto/timex)

您可以编写自定义vadlidate_time_range函数,并在changeset函数中使用它在管道内。 那些验证器需要将changeset结构作为第一个参数并返回changeset结构。 在此功能中,您需要检查两个日期。 如果他们改变了,他们将处于changeset.changes 。 如果没有,您将需要从模型中提取它们。 你可以这样得到它们: start_time = changeset.changes |> Dict.get(:start_time, nil) start_time =

通用方法获取唯一参数并返回唯一参数Java(Generic Method That takes unique parameter and returns unique parameters Java)

创建interface Foo并在paramObject1和paramObject2类中实现此interface 。 现在你的方法应该是这样的: public Foo myFunction(Foo foo, int a){ //Rest of the code. return foo; } Make interface Foo and implement this interface in both paramObject1 and paramObject2 class. No

相关文章

更多

最新问答

更多
  • 图像TapGestureRecognizer未触发(Image TapGestureRecognizer not firing)
  • 从数组中选择项目(Selecting items from an array)
  • PhpStorm:简单的PHP表单不发布(PhpStorm: Simple PHP form not posting)
  • 如果语句只有Javascript中的数字(If statement with only a number in Javascript)
  • 截图Android中的黑色(Screenshot Black in Android)
  • 默认值如何在数据库中内部工作?(How does default value internally work in Database?)
  • 左连接不加入单个记录(Left Join Not Joining with a Single Record)
  • 在#sign drupal之后获取url参数(get url parameter after # sign drupal)
  • Crontab CD到目录(Crontab CD to Directory)
  • #inf c ++ visual studio(#inf c++ visual studio)
  • 使用Python将指数修改的高斯曲线拟合到数据(Fitting an exponential modified gaussian curve to data with Python)
  • Javascript - 具有音高和持续时间控制的文本到语音(Javascript - text to speech with pitch and duration control)
  • 群组和用户有多少通过?(Groups and Users has many oder has many through?)
  • 如何在简单的二叉树中选择节点所在的哪一侧?(How to pick which side a node is on in a simple binary tree?)
  • 在ImageView上添加TextView(Android)(Add TextView over ImageView (Android))
  • 使用工厂方法创建泛型(Using Factory Method to Create Generics)
  • cordova 4.1.2中的平台特定代码(platform specific code in cordova 4.1.2)
  • 使用php格式化日期[复制](Format date using php [duplicate])
  • 在Python中解析年,月,日,小时,分钟,秒(Parsing year, month, day, hour, minute, second in Python)
  • 用jquery替换图像和类(Replacing image and class with jquery)
  • 导入的module.submodule命名空间干扰彼此(imported module.submodule namespaces interfering with eachother)
  • 播放框架:提交按钮似乎不起作用(Play framework: Submit button doesn't seem to work)
  • 段落包括通过过渡带来的div(Paragraph covers div brought through transition)
  • 使用processing.Manager时对象是否重复?(Object duplicated when using processing.Manager?)
  • lxde意外退出(lxde quits unexpectedly)
  • 真正的Maven依赖是什么?(What really are Maven dependencies?)
  • 如何在我的代码中修复getJSON方法错误?(how to fix getJSON method error in my code?)
  • Google Analytics状态:已安装跟踪 - 但无法正常运行(Google Analytics Status: Tracking Installed - but isnt working)
  • 在模型文件中的非对象上调用成员函数num_rows()(Call to a member function num_rows() on a non-object in model file)
  • 有关UNIX中fork()函数的问题(Questions about the fork() function in UNIX)