【问题标题】:Pass parameter on constructor or pass them on each method在构造函数上传递参数或在每个方法上传递它们
【发布时间】:2019-11-27 17:00:00
【问题描述】:

我正在学习 C++,我有这个头文件:

#ifndef _ROBOT_MOVE_H__
#define _ROBOT_MOVE_H__ 1

#include "ros/ros.h"

class RobotMove
{
private:
    double current_linear;
    double current_angular;
public:
    void TurnLeft(const ros::Publisher& publisher, ros::Rate& loop_rate);
    void TurnRight(const ros::Publisher& publisher, ros::Rate& loop_rate);
    void TurnAround(const ros::Publisher& publisher, ros::Rate& loop_rate);
    void Forward(const ros::Publisher& publisher, ros::Rate& loop_rate);
    void Backward(const ros::Publisher& publisher, ros::Rate& loop_rate);
    void Stop();

    RobotMove();
    ~RobotMove();
}


#endif

我不知道最好在构造函数上传递一次const ros::Publisher& publisher, ros::Rate& loop_rate,还是每次调用其他方法时传递它们。

在构造函数中传递这两个参数并在类中存储一个指针更好还是在每个方法上传递它们?

顺便说一下,这两个参数总是相同的对象。

【问题讨论】:

  • #define _ROBOT_MOVE_H__ 这是一个保留的标识符。通过定义它,程序将具有未定义的行为。
  • 这取决于很多事情。
  • 另外,这很有可能得到纯属固执己见的答案。
  • 构造函数的工作是创建一个函数对象并建立/满足类不变量。如果需要传递参数来做到这一点,它应该是一个构造函数参数。如果它不是必需的并且对象可以在没有的情况下使用,那么它可以稍后传递给函数。
  • #ifndef _ROBOT_MOVE_H__ - 这是一个非常糟糕的标题守卫名称。它符合语言的两条规则: 1) 任何以下划线开头后跟大写字母的名称都保留用于实现。 2) 任何包含双下划线 anywhere 的名称都保留用于实现。您不允许在您自己的代码中使用此类名称,这样做会导致您的代码具有未定义的行为并且整个程序基本上是无效的。

标签: c++ design-patterns software-design


【解决方案1】:

顺便说一下,这两个参数总是相同的对象。

对我来说,这表明它们应该是类的成员变量。使它们成为类的成员变量遵循Don't Repeat Yourself (DRY) principle。因此,在构造函数中传递它们并让对象将它们存储为成员变量是有意义的。

【讨论】:

  • 非常感谢您的回答。也许我可以存储对这两个变量的引用。我是 C++ 新手,我不知道该怎么做。对于引用,我的意思是不创建复制对象或新实例。谢谢。
  • 你当然可以。使成员变量引用类型并确保在构造函数中初始化它们。例如:struct Foo { int& ref; Foo(int& in) : ref(in) {} };
【解决方案2】:

这是一个很好的基本问题。

要回答这个问题,你可以问自己are these parameters specific to each action(method) or are they objects used by an instance of the class in general ?

在您的示例中,给出了您的类和方法的名称,事实上有这么多方法使用它们并且您还指定它们不会改变,我建议将它们传递给构造函数而不是每次调用。

但这并不总是正确的答案,您必须根据您认为这些参数可能更改的频率以及您希望赋予类的语义意义及其与这些参数的关系来判断和平衡。

我知道这听起来很浮夸,但设计选择通常取决于上下文。

【讨论】:

  • 感谢您的回答。这些对象永远不会改变。
【解决方案3】:

我想说的是,从编程的角度来看,您需要一次又一次地复制和粘贴相同的代码越少越好。这就是编程的目的,让计算机为你重复一些事情。我会将这些参数传递给构造函数,然后将它们存储为属性。我相信你会像下面这样实现它:

class RobotMove
{
private:
    double current_linear;
    double current_angular;
    const ros::Publisher * publisher;
    ros::Rate * loop_rate;

public:
    RobotMove(const ros::Publisher& publisher, ros::Rate& loop_rate)
    {
        this->publisher = &publisher;
        this->loop_rate = &loop_rate;
    }
};

【讨论】:

  • 请记住,“减少复制和粘贴”本身并不是进行这样的结构更改的好理由。有时这样做会导致过度简化和混乱。可用性应该是这些类型决策的主要因素。
  • @FrançoisAndrieux 我上面的编辑说明会更好吗?
  • @Chipster 这将消除每次都必须传递这两个参数,而只需在构造函数中执行一次,对吗?我觉得那会是一个更好的设计?
  • @StormsEngineering 我同意,那将是更好的设计。我只是说你给出的理由不一定是一个好的理由本身。在这种情况下,还有其他原因也表明它需要移动到构造函数,所以最后,你是对的。我只是不同意你为此付出的理由。
  • @Chipster 对,这很有意义。感谢您的澄清!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-09-04
  • 2014-09-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多