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

What is a good way to validate input?

本文关键字:是什么 方法 输入 验证      更新时间:2023-10-16

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

class Sphere
{
public:
    void setRadius(double radius)
    {
        m_radius = radius;
    }
private:
    double m_radius; // must >= 0.
};

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

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

在OOP中,通常让验证发生在函数中,如果值不在您的可接受范围内,则让函数抛出异常。

然而,如果你正在为一个类做这件事,并且还不希望知道抛出/捕获异常,你可以做以下两件事之一:

  1. 让你的函数返回int, bool等。如果参数在范围内,那么你的函数返回一些值来表示。否则,函数返回一些值,指示参数不在范围内。

像这样:

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

注意,如果"radius"的参数不在你的范围内,你不能初始化/改变存储在m_radius中的值。将m_radius的值更改为不可接受的值是没有意义的——这是浪费时间。

  1. 检查main() ("in the dialog"?)

如果你想知道更多关于异常的知识,你可以参考这个页面来更好地理解什么是异常:http://www.cplusplus.com/doc/tutorial/exceptions/

所以,i++,总结一下,约定是在方法中检查它,如果值超出可接受范围,则让方法抛出异常。如果你正在上课并且还没有涉及异常,你可能不需要。祝你好运!:)

我可以在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_;
};

我建议采用一种不同于其他方法的方法。我就把值存储在这里。相反,看看我的水晶球,当在球体上调用Render(Image& target)函数时,我将验证所有参数是否合适。也可以采用混合方法,在setter中验证半径是非负浮点数,同时在渲染时验证球体是否在图像的边界内。

这两种方法有一个根本的区别:

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

在我看来,这是太多的面向对象。对于少于2 - 3个变量,我不会创建具有getter-setter和私有数据的类——这没有意义。它需要大量不必要的代码。

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

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