警告函数的调用者必须处理

时间:2010-04-06 19:21:58

标签: c++ exception

我正在寻找一种方法来设置调用者必须响应的警告。在某种意义上,我想使用在函数已经完成执行并返回所需值之后发生的延迟异常机制。

SomeObject Foo(int input)
{
   SomeObject result;      
   // do something. oh, we need to warn the caller. 

   return result;
}

void Main()
{
   SomeObject object;
   object = Foo(1); // after copy constructor is done I would like an exception to be thrown


}

3 个答案:

答案 0 :(得分:4)

我认为你必须做出更具体的决定。 (某种程度上)警告用户使用某个功能同时给他们一个结果是非常不正统的。

例如,您可以返回std::pair<SomeObject, std::string>,其中警告在字符串中,如果有的话。但人们很容易忽视这一点。

异常不是解决方案:如果你能以一种有意义的方式继续执行,那就不是特殊的情况了。有可能想出一些系统让他们在某个地方以“队列”的形式完成异常,但什么时候应该被抛出?为了什么目的?当然,无论如何它最终会削减其余的工作。

我认为你想要的是assertassert条件成立;如果没有,程序员将收到通知,并可以相应地处理这种情况。请记住,assert是针对程序员的,例外是针对程序的。

也许如果你给我们一个更具体的例子,我们就能够提出最好的行动方案。

答案 1 :(得分:0)

投掷“例外”并继续“恢复正常价值”的矛盾。

正如您所写,您可以记住问题发生在SomeObject的某个成员或某个变量中,该变量作为对构造函数的引用传递。

为了防止调用者不处理错误,您可以构造一个“信令成员”,如果调用者没有轮询它,您将在SomeObject的析构函数中断言(或在信令成员的析构函数中)。

信令成员的可能示例:

template <typename Base>
class Signal
{
private:
  Base _val;
  bool _polled;

public:
  operator Base() const {_polled=true;return _val;}
  // even when we do not set the value, we force the user to poll - it makes testing easier
  Signal():_polled(false) {}
  // but once we set it, we mark he has to poll
  Signal(Base val):_val(val),_polled(false) {}
  // if he does not, we assert
  ~Signal(){assert(_polled);}
};

如果设置了值并且调用者不会“获取”它,则析构函数将断言。如果调用者会得到它但无论如何都会忽略,那么你就是运气不好 - 但是这也是一样的例外:如果调用者捕获它并忽略它,你就无法做到这一点。以下是您将如何使用它:

SomeObject Foo(int input, Signal<int> &errorCode)
{
  SomeObject result;      
  // do something. 
  if (somethingBadHappened)
    errorCode = 1234; //oh, we need to warn the caller. 

  return result;
}

void Main()
{
  SomeObject object;
  Signal<int> error;
  object = Foo(1,error);

  // error not served? => assert
  // to prevent the assert firing, uncomment the following line
  // int handle = error;
}

注意:您也可以在Signal析构函数中抛出异常,而不是断言。但是要注意,从析构函数中抛出很难正确 - 你需要特别注意你如何使用Signal类(以及将用作它的Base)。

答案 2 :(得分:-1)

当抛出异常时,编译器将依次查看每个堆栈帧,从当前开始,并查找可以处理抛出的异常类型的catch块。

当编译器查看每个堆栈帧时,它会清除该帧中的所有局部变量 - 因此,即使您的函数返回一个值,然后在“函数已经完成执行后”抛出异常,返回当编译器解开堆栈时,无论如何都会清除值。那么等待功能完成的重点是什么?只需在那里抛出异常然后:

SomeObject foo(int input)
{
   SomeObject result;

   // Do stuff

   // Something goes wrong in an unrecoverable fashion
   throw BadThingHappenedException;

   // More code for the good case
   return result;
}