什么是验证输入的好方法?

时间:2013-01-20 05:02:29

标签: c++ validation

我有一个类,其中一些成员的值具有有限的范围。例如

class Sphere
{
public:
    void setRadius(double radius)
    {
        m_radius = radius;
    }

private:
    double m_radius; // must >= 0.
};

我还有一个输入半径的对话框。我可以在setRadius()方法中检查半径验证,或者检查对话框。哪种方式更好?这似乎是一个非常普遍的问题。什么是传统方式或最佳方式?感谢。

5 个答案:

答案 0 :(得分:3)

我假设将根据用户输入调用set方法。如果是这样,传统的方法是set方法在提供异常值时抛出异常。该异常应该一直传播到UI

答案 1 :(得分:1)

  

我可以在setRadius()方法中检查半径验证,或检查   在对话框中。哪种方式更好?

如果系统非常小并且GUI相对简单,您可以检查对话框类中的输入。另一种解决方案是提供第三类作为输入验证策略,用于检查用户输入。

下面是一个非常简单的演示代码,可以使用模板为不同的GUI设置不同的策略。

class CheckPolicy
{
public:
  CheckPolicy() {}

  virtual bool ValidInput(double f)
  {
    return f > 0;
  }
};

class GUI
{
public:
  GUI(){}
  void GetInput()
  {
      float f = 1.0f;
      if (policy_.ValidInput(f))
      {
        sphere_.setRadius(f);
      }
  }
private:
  CheckPolicy policy_;
  Sphere      sphere_;
};

答案 2 :(得分:1)

在OOP中,您通常会在函数中进行验证,并且如果值不在您接受的范围内,则函数会抛出异常(在您的情况下)。

但是,如果您正在为一个类执行此操作,并且预计不会知道抛出/捕获异常,则可以执行以下两项操作之一:

  1. 让你的函数返回一个int,bool等。如果参数在范围内,那么你的函数会返回一个指示的值。否则,该函数返回一些值,表明参数不在范围内。
  2. 这样的事情:

    bool setRadius(double radius)
    {
        if(radius >= 0)
        {
            m_radius = radius;
            return true;
        }
        else return false;
    }
    

    请注意,如果“radius”的参数不在您的范围内,则不会启动/更改存储在m_radius中的值。将m_radius的值更改为不可接受的值是没有意义的 - 这是浪费时间。

    1. 在main()中检查(“在对话框中?”)
    2. 如果您想了解有关例外的更多信息,可以参考此页面以更好地了解例外情况:http://www.cplusplus.com/doc/tutorial/exceptions/

      因此,i ++并得出结论,惯例是在方法中检查它,如果值超出可接受的范围,则让方法抛出异常。如果您在课堂上并且尚未涵盖例外,则可能没有必要。祝你好运! :)

答案 3 :(得分:1)

我建议采用与其他方法不同的方法。我只是将值存储在那里。相反,看着我的水晶球,在球体上调用Render(Image& target)函数时,我将验证所有参数是否合适。也可以使用混合方法,在渲染时验证球体在图像范围内时,验证半径是设置器中的非负浮点数。

方法之间存在根本区别:

  • 不允许半径有效变为负值意味着非负半径是类不变量。将所有类不变量的验证放入一个实用程序函数中,在所有(变异)成员函数的进入和退出时通过RAII帮助程序调用它是一个好处,因为它可以在内部状态(可能更多)时立即捕获复杂而不仅仅是一个标量)在某种程度上变得不一致。为了速度,我通常会对发布二进制文件禁用这些检查,因此即使进行大量检查,您也不会失去任何性能。
  • 允许半径变为负数但稍后引发异常会将其转换为由使用该值的操作(例如渲染)引起的故障。在某些情况下,这会使无效输入值与该操作期间的内存不可区分,但它的优点是您只需将这些错误捕获到一个位置。

答案 4 :(得分:0)

在我看来,这太过于面向对象了。对于不到两三个变量,我不会创建一个具有getter-setter和私有数据的类 - 它没有意义。它需要很多不必要的代码。

您最好在UI前端进行数据验证(例如通过DoDataExchange)。

如果您必须设计一个类来保存数据并进行数据验证,请使用模板!