当我在一个类中设计一个函数时,我想平衡我可以从中提取的信息。某些信息可能对调试很有用,但作为函数的输出不是必需的。我给出以下示例:
class A
{
bool my_func(int arg1, int &output, std::vector<int> &intermediate_vec);
{
// do something
}
}
在函数my_func
中,std::vector<int> &intermediate_vec
不是必需的,因为我感兴趣的唯一信息存储在变量output
中。但是,出于调试目的,我也对获取intermediate_vec
感兴趣,因为由于某种原因在函数内检查此变量是不方便的。因此,我正在考虑在A类中设计两个函数,一个用于调试,另一个用于实际应用。
class A
{
// for debug
bool my_func(int arg1, int &output, std::vector<int> &intermediate_vec);
{
// do something
}
// invoked by other programs
bool my_func(int arg1, int &output);
{
// do something
std::vector<int> intermediate_vec
return my_func(arg1, output, intermediate_vec);
}
}
我只是想知道有更好的方法来完成这项工作。谢谢。
答案 0 :(得分:5)
使用日志记录库并在调试日志级别记录这些中间值,而不是将它们作为输出收集。
答案 1 :(得分:1)
如果您计划在某些调试后期处理中使用intermediate_vec
,那可能会非常棘手。但是,如果您只打算使用它来打印结果就更容易了。
我不喜欢你的想法是在两个不同的地方让//do something
看起来完全一样。这非常容易出错,并开始成为一个真正的PIA,当你需要用十几种方法维护十几个类时,其中一半有一些调试副本。逻辑的每一次变化都必须以连贯的方式完成两次。
当我遇到类似的问题时,我正在考虑遵循一些事情,以避免在执行条件记录和/或其他仪器时加倍逻辑。
<强> #define DEBUG/NDEBUG
强>
你只需要一份带有一些预处理器条件的代码副本。
<强> template < int DEBUG >
即可。
基本上效果相同但语义不同。
模板方法可能会使编码稍微复杂化,但它允许在运行时使用这两个版本,这可能会派上用场。 #define
方法根本不会改变API,但是在设计代码时你真的需要考虑如果你想要一些精彩的选择性或多级调试。
两个函数方法在我的用例中没问题,因为我必须拥有安全版本和快速版本的例程。保险箱做了一些检查,然后叫快速数字计算器。如果数字cruncher用于循环或内部,可以安全地假设您可以跳过检查,这非常有用。
如果调试版本较慢(例如'casue,您需要初始化并填充长向量),那么您可能不希望在发布代码中调用它。记录也是如此。如果你真的需要输出一个数字,但在调试版本中你将最终打印数兆字节的数据(例如计算向量的范数并打印向量本身),你将需要使用条件记录。
总的来说,这看起来更像是这样:
class A
{
bool my_func(int arg1, int &output, std::vector<int> &intermediate_vec);
{
if(DEBUG) {//fill in the vector}
// do something
if(DEBUG) {//print out some fancy stuff}
}
// invoked by other programs
bool my_func(int arg1, int &output);
{
std::vector<int> intermediate_vec;
return my_func(arg1, output, intermediate_vec);
}
}
当然,你可以使用调试的短调用,但你不会得到向量。或者在非调试模式下完全调用,但intermediate_vec
没有意义。
任何可以避免复制粘贴应用程序逻辑的东西。我做到了,在改变逻辑方面,我非常痛苦。