如何在不破坏现有代码的情况下向函数添加输出参数?

时间:2012-11-08 17:31:56

标签: c++ function parameters

我假设函数已经有一个返回值,因此无法添加。

我想出来解决这个问题的方法是添加额外的指针参数,默认为nullptr。

在:

bool fun(double a, std::vector<std::randomexample> const & b)

后:

bool fun(double a, std::vector<std::randomexample> const & b, int* extraoutput = nullptr)

并像这样使用

if(extraoutput)
  *extraoutput = whatever;

但这就是我想出来的。 我想知道是否有更好的方法来做到这一点。请注意,函数中已经存在“无论什么”。

5 个答案:

答案 0 :(得分:4)

如果出于某种原因,您需要二进制以及(主要)源兼容性[*]:

在:

bool fun(double a, std::vector<std::randomexample> const & b) {
    // do stuff
    return true;
}

后:

bool fun(double a, std::vector<std::randomexample> const & b, int* extraoutput) {
    // do stuff
    if(extraoutput)
        *extraoutput = whatever;
    return true;
}
bool fun(double a, std::vector<std::randomexample> const & b) {
    return fun(a, b, nullptr);
}

如果您不想要函数重载(例如,如果funextern "C"接口的一部分),那么您实际上不必调用新函数fun。它也可以是fun2

[*]正如AndreyT所指出的,您的解决方案的源兼容性是有限的。调用你的旧函数会调用你的新函数,但是你可能用旧函数做的其他一些事情也不会正常工作(因为你改变了它的类型)。

我的代码实际上也存在源代码不兼容的问题。在添加重载之前允许void(*foo)() = (void(*)()) fun;,但之后它是不明确的。如果你想支持那样做的代码,那么这就是不希望函数重载的第二个原因。

答案 1 :(得分:2)

通常,我使用额外参数添加方法,并使用前一种方法的默认值调用该方法:

//foo v1
void foo( S s ) {
   ... stuff with s;
};

//codeA_v1:
S s;
foo(s);

//codeB_v1
S s2;
foo(s2);

然后,我添加一个带有额外参数的方法:

void foo(S s){ foo(s, default_value_for_T); }
void foo(S s, T t){
   ... stuff with s and t
}

//codeA_v1 == codeA_v2
S s;
foo(s);

//codeB_v2
S s;
T t;
foo(s,t);

答案 2 :(得分:2)

这是一个扩展评论。正如其他人所建议的那样,你最好使函数重载以提供源和二进制兼容性。这样做的原因是通过引入功能签名的更改,您还可以更改损坏的符号名称,例如,从_Z3fundRKSt6vectorISt13randomexampleSaIS0_EE_Z3fundRKSt6vectorISt13randomexampleSaIS0_EEPi。这将破坏与其旧的受损名称调用fun()的所有其他对象的二进制兼容性。如果fun()是动态链接库的一部分,它将破坏链接它的所有现有二进制文件,因为动态链接器将无法再解析_Z3fundRKSt6vectorISt13randomexampleSaIS0_EE符号引用。如果你使用重载函数版本,旧的受损符号仍然存在,并且将保留二进制兼容性。

答案 3 :(得分:0)

正如其他人所说,这将是您的最终产品。

bool fun(double a, std::vector<std::randomexample> const & b){
    return fun(a,b,0);
}
bool fun(double a, std::vector<std::randomexample> const & b, int* extraoutput = 0){
    // have fun!
    if(extraoutput) *extraoutput = whatever;
    return true;
}

答案 4 :(得分:-1)

您可以尝试实现genernic Observer模式。 这是一个像: http://sourcemaking.com/design_patterns/observer

如果您想要添加更多参数,将来会更好。如果你不能导出那么作为参数传递也将是解决方案。

据我所知,你必须在这个功能中做到这一点,否则是过载是一个很好的解决方案。

除了其他解决方案之外,它不会破坏二进制兼容性。