如何从方法返回可选的调试信息?

时间:2016-10-22 10:45:32

标签: c++ oop debugging fuzzy-comparison

假设我有一个静态方法,它比较两个对象的近似匹配并返回一些置信度[0,1]。

class Foo
{
  ...
  static double Compare(const Foo& foo1, const Foo& foo2);
  ...
};

现在,我需要根据配置中的设置返回包含比较详细信息的其他调试信息。 由于此调试信息不​​会在生产中使用,但仅在测试/调试目的时,我想知道实现它的适当方法是什么。

我至少看到三个选项:

1:在那里创建一个额外的类CompareResult并存储置信度+可选信息。如果您不需要,请不要填写可选信息​​。

class CompareResult
{
  ...
private:
  double confidence_;
  CompareOptionalInfo compare_optional_info_;
  ...
};

...

static CompareResult Compare(const Foo& foo1, const Foo& foo2);

它似乎是最干净的,但我不确定是否应该将返回结果与可选信息结合起来。

2:使用输出变量(这样我们就不需要创建一个额外的类,但我们的方法签名会增长一点)

static double Compare(const Foo& foo1, const Foo& foo2, CompareOptionalInfo* out_compare_info = nullptr);

3:使用可选信息检索方法单独比较方法。

static double Compare(const Foo& foo1, const Foo& foo2);
static CompareOptionalInfo GetCompareOptionalInfo();

此选项可能需要在方法调用之间存储此可选信息,并从静态比较方法转换为实例比较方法。 但同样,我不确定它是否合适。

根据您的经验,OOP世界中从方法返回可选信息(主要仅在调试模式下使用)的适当方式是什么?

2 个答案:

答案 0 :(得分:1)

选项3 根本不是一个好主意:拥有依赖于静态数据的功能是不切实际的,甚至可能成为调试中的错误来源。这样的设计另外不是线程安全的;可惜的是,仅为了调试目的而创建这样的限制!

问题的例子:

double closest = std::max (Foo::compare (x, y), Foo::compare (y,z));   
clog << Foo::GetCompareOptionalInfo();  // undefined which info since order of eval
                                        // of function parameter is not guaranteed

double d = Foo::compare (x, y); 
DoSomething();                    // what if this one does an unexpected  compare ? 
clog << Foo::GetCompareOptionalInfo();  

选项2 是一个可行的解决方案,但它不是很方便:它会强制您创建信息对象,通过地址等传递它们:

Foo::OptionalCompareInfo o1,o2;    // cumbersome 
double closest = std::max (Foo::compare (x, y, &o1), Foo::compare (y,z, &o2));   

此外,您将创建这些可选信息并在生产中传递额外参数,即使您不再更新其中的信息(除非您进行了大量额外的条件编译)!

选项1 非常好!去吧 !它真正受益于OOP范例,并采用了简洁的设计。使用它很实用,并且不会对您的代码施加约束来使用它。

您只需提供一些(隐式)转换功能即可使用CompareResult,就好像它是double一样:

class CompareResult
{
public:
  CompareResult(double d=0.0) : confidence_(d) {}; 
  operator double() { return confidence_; }
  operator bool() { return confidence_>0.5; }   
private:
  double confidence_;
  CompareOptionalInfo compare_optional_info_;
};

online demo

您的生产代码不受调试信息的影响。您可以在调试中随时追溯任何给定比较结果的解释,至少如果您存储它:

示例:

auto result = Foo::compare (x, y)
if (result) ... // uses automatically the conversion

auto closest = std::max (Foo::compare (x, y), Foo::compare (y,z));
// here you not only know the closest match but could explain it ! 

vector<CompareResult> v;  
... // populate the vector with 10 000 comparison results
auto r = std::max_element(v.begin(), v.end());  
    // you could still explain the compare info for the largest value 
    // if you're interested in the details of this single value
    // how would you do this with option 3 or option 2 ?     

好的,对于最后一个工作,你还需要一个比较运算符来为你的额外课程。但是这一行代码更多(参见在线演示);-)

最后,可能会发现您的&#34;可选调试信息&#34;可以证明比预期更有用,例如根据要求向用户提供额外的解释。您需要做的就是删除围绕可选信息计算的条件#ifdef DEBUG

答案 1 :(得分:0)

我会使用第二个选项来兼容调试器。

在调试模式下,您可以添加其他静态成员。您应该注意不应该禁止它的链接器。

class Foo
{
  private:
#ifndef NDEBUG
  CompareOptionalInfo debug_out_compare_info_;
#endif

  ...
  static double Compare(const Foo& foo1, const Foo& foo2,
         CompareOptionalInfo* out_compare_info = nullptr);
  ...
};

#ifndef NDEBUG
CompareOptionalInfo Foo::debug_out_compare_info_;
#endif

在gdb中,在任何断点处,您都可以使用:

call Foo::Compare(foo1, foo2, &Foo::debug_out_compare_info_);
print Foo::debug_out_compare_info_. ...