c++ - 允许函数抛出或抛出构造函数更好吗?

标签 c++

我认为,使用示例更容易解释。让我们上一堂模拟一级方程式赛车速度的类(class),界面可能类似于:

class SpeedF1
{
public:
  explicit SpeedF1(double speed);
  double getSpeed() const;
  void setSpeed(double newSpeed);
  //other stuff as unit 
private:
  double speed_;
};

现在,负速度在这种特殊情况下没有意义,并且任何值都不大于 500 公里/小时。在这种情况下,如果提供的值不在逻辑范围内,构造函数和 setSpeed 函数可能会抛出异常。

我可以引入一个额外的抽象层并插入一个额外的对象而不是 double。 新对象将是 double 的包装器,它将被构造并且永远不会修改。 该类的接口(interface)将更改为:

class ReasonableSpeed
{
public:
  explicit ReasonableSpeed(double speed); //may throw a logic error
  double getSpeed() const;
  //no setter are provide
private:
  double speed_;
};

class SpeedF1
{
public:
  explicit SpeedF1(const ReasonableSpeed& speed);
  ReasonableSpeed getSpeed() const;
  void setSpeed(const ReasonableSpeed& newSpeed);
  //other stuff as unit 
private:
  ReasonableSpeed speed_;
};

采用这种设计,SpeedF1 无法抛出,但是每次我想重置速度时,我都需要额外支付一个对象构造函数。

对于一组有限的值是合理的类(例如日历中的月份),我通常将构造函数设为私有(private)并提供一组完整的静态函数。在这种情况下,这是不可能的,另一种可能性是实现空对象模式,但我不确定它是否优于简单地抛出异常。

最后,我的问题是:

解决此类问题的最佳做法是什么?

最佳答案

首先,不要高估额外构造函数的成本。事实上,这个成本应该正好是初始化一个double 的成本加上有效性检查的成本。换句话说,它很可能等于使用原始double

其次,失去二传手。 Setters – and, to a lesser degree, getters – are almost always anti-patterns.如果您需要设置一个新的(最大)速度,您可能真的想要一辆新车。

现在,关于实际问题:抛出构造函数原则上完全没问题。不要编写复杂的代码以避免这种构造。

另一方面,我也喜欢自检类型的想法。这充分利用了 C++ 的类型系统,我完全赞成这一点。

这两种选择各有优势。哪一个最好取决于具体情况。总的来说,我尝试尽可能多地利用类型系统和静态类型检查。在您的情况下,这意味着有一个额外的速度类型。

关于c++ - 允许函数抛出或抛出构造函数更好吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7215591/

相关文章:

c++ - std::thread::swap的目的是什么?

c++ - push_backs 到 std::vector<std::reference_wrapper<type>>

c++ - 在 C++ 中使用运算符 "="用值初始化对象

c++ - 为什么这个循环不加载正确的事件?

c++ - 为什么不只有一个?复制构造函数和赋值运算符

c++ - atomic_compare_exchange 大于而不是等于?

c++ - 如何确定 C++ 中的 IP 版本?

c++ - 初始化类的静态常量非整型数据成员

c++ - 流 C++ 的多个函数

c++ - 使用 STL 在 C++ 中对字符串进行标记