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

C++ 如何在不破坏现有代码的情况下向函数添加输出参数?,c++,function,parameters,C++,Function,Parameters,我假设函数已经有一个返回值,因此无法添加该值 我想出的解决这个问题的办法是添加默认为nullptr的额外指针参数 之前: bool fun(double a, std::vector<std::randomexample> const & b) bool fun(double a, std::vector<std::randomexample> const & b) { // do stuff return true; } 但这正是我想

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

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

之前:

bool fun(double a, std::vector<std::randomexample> const & b)
bool fun(double a, std::vector<std::randomexample> const & b) {
    // do stuff
    return true;
}
但这正是我想到的。
我想知道是否有更好的方法来做到这一点。请注意,“whatever”已经在函数中。

您可以尝试实现genernic Observer模式。 这里有一个类似的例子:

当您希望添加更多参数时,这对将来会更好。如果您不能派生,那么作为参数传递也是一种解决方案

据我所知,您必须在这个函数中执行此操作,否则yes重载是一个很好的解决方案


它不会破坏与其他解决方案的二进制兼容性。

如其他人所述,这将是您的最终产品

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;
}
bool-fun(双a,标准::向量常量和b){
返回乐趣(a、b、0);
}
bool-fun(双a,标准::向量常量和b,int*extraoutput=0){
//玩得开心!
如果(extraoutput)*extraoutput=任意值;
返回true;
}

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

之前:

bool fun(double a, std::vector<std::randomexample> const & b)
bool fun(double a, std::vector<std::randomexample> const & b) {
    // do stuff
    return true;
}
bool-fun(双a,标准::向量常量和b){
//做事
返回true;
}
之后:

bool fun(double a, std::vector<std::randomexample> const & b, int* extraoutput = nullptr)
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);
}
bool-fun(双a,标准::向量常量和b,int*额外输出){
//做事
if(外部输出)
*额外输出=无论什么;
返回true;
}
bool-fun(双a,标准::向量常量和b){
返回乐趣(a、b、空PTR);
}
如果不希望函数重载(例如,如果
fun
extern“C”
接口的一部分),则实际上不必调用新函数
fun
。它也可以是
fun2

[*]正如AndreyT指出的,解决方案的源代码兼容性是有限的。对旧函数的调用将很好地调用新函数,但对旧函数可能执行的其他一些操作将无法正常工作(因为您已更改了它的类型)

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

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

//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);

这是一个延伸的评论。正如其他人所建议的,为了提供源代码和二进制代码的兼容性,最好重载函数。这样做的原因是,通过在函数签名中引入更改,您还可以更改损坏的符号名称,例如,从
更改为
。这将破坏与所有其他对象的二进制兼容性,这些对象通过其旧名称调用
fun()
。如果
fun()
是动态链接库的一部分,它将断开与之链接的所有现有二进制文件,因为动态链接器将不再能够解析
\u z3FundRkst6Vectorist13RandomExampleSais0ee
符号引用。如果使用重载函数版本,旧的损坏符号将仍然存在,二进制兼容性将保留。

如果您绝对不想更改现有的内容,请创建一个新的重载符号。这是否真的与当前情况相关?更通用的解决方案始终是一种情况,我认为将来会有更多的参数进入游戏。@Cthulhu:可能是的。现在添加一个可选的新参数,该参数当前具有
observewhatever
函数。当同样的事情再次发生时,您不必向函数添加另一个可选指针参数,您可以向观察者添加另一个函数。我认为这不是观察者模式的一个好应用。IMHO回调使一切变得更加复杂。我关心未来的二进制兼容性。请记住,破坏的compability可能会非常昂贵。在这种情况下,您必须删除默认参数,因为否则使用2个参数的调用将变得不明确。最好在新函数中创建该extraoutput并将其作为引用传递。可能能够保存一些复制,调用将不再含糊不清。为什么旧函数的类型会更改?我的意思是,旧函数现在只调用新函数,因此内容似乎发生了更改,但我不明白为什么类型会更改。@下士:你函数的类型
bool-fun(double-a,Foo-const&b)
bool(double,Foo-const&)
。函数的类型是
bool(double a,Foo-const&b,int*extraoutput=nullptr)
bool(double,Foo-const&int*)
。这两者不一样。在我的代码中,除了新函数之外,还有一个类型为
bool(double,Foo const&)
的函数,因此依赖于旧类型的代码是可以的。啊,好的,所以这实际上不是您的解决方案中的问题,而是我的解决方案中的问题。对不起,我弄糊涂了。:)@CorporatalTouch:是的,在您的解决方案中,如果有人确实通过函数指针变量调用函数,那么他们不仅需要更改变量的类型,还必须显式地为第三个参数提供一个值。基本上,调用代码需要“知道”默认值,它不是函数的属性,函数指针也不知道。但是,如果人们只按名字调用你的函数,那就没问题了。