5

関数には既に戻り値があるため、追加できないと想定しています。

この問題を解決するために私が思いついたのは、デフォルトで 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;

しかし、それは私が思いついたものです。これを行うためのより良い方法があるかどうかを知りたいです。"whatever" は既に関数に含まれていることに注意してください。

4

5 に答える 5

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

関数のオーバーロードが必要ない場合 (たとえば、がインターフェイスfunの一部である場合extern "C")、実際に new function を呼び出す必要はありませんfun。それはちょうどよいかもしれませんfun2

[*] AndreyT が指摘しているように、ソリューションのソース互換性は限られています。古い関数を呼び出すと、新しい関数が正常に呼び出されますが、古い関数で行う可能性のある他のいくつかのことは正常に機能しません (型を変更したため)。

実際、私のコードにもソースの非互換性があります。void(*foo)() = (void(*)()) fun;オーバーロードが追加される前は許可されますが、その後はあいまいです。それを行うコードをサポートしたい場合、それが関数のオーバーロードを望まない 2 つ目の理由です。

于 2012-11-08T17:37:17.207 に答える
2

これは拡張コメントです。他の人がすでに示唆しているように、ソースとバイナリの両方の互換性を提供するには、関数をオーバーロードする方がよいでしょう。これを行う理由は、関数のシグネチャに変更を加えることで、マングルされたシンボル名も変更するためです。たとえば、から_Z3fundRKSt6vectorISt13randomexampleSaIS0_EEに変更し_Z3fundRKSt6vectorISt13randomexampleSaIS0_EEPiます。fun()これにより、古いマングル名で呼び出す他のすべてのオブジェクトとのバイナリ互換性が失われます。が動的にリンクされたライブラリの一部である場合、動的リンカーはシンボル参照fun()を解決できなくなるため、それに対してリンクしている既存のすべてのバイナリが壊れます。_Z3fundRKSt6vectorISt13randomexampleSaIS0_EEオーバーロードされた関数バージョンを使用する場合、古いマングルされたシンボルは引き続き存在し、バイナリ互換性は保持されます。

于 2012-11-08T17:51:11.150 に答える
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);
于 2012-11-08T17:40:53.037 に答える
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;
}
于 2012-11-08T17:37:15.050 に答える
-1

一般的な Observer パターンの実装を試すことができます。これは次のようなものです: http://sourcemaking.com/design_patterns/observer

将来、さらにパラメータを追加したい場合に備えてください。派生できない場合は、パラメーターとして渡すことも解決策になります。

私が理解しているように、この関数でそれを行う必要があります。そうでない場合は、オーバーロードが良い解決策です。

それ以外の場合は、他のソリューションとのバイナリ互換性が損なわれません。

于 2012-11-08T17:35:37.300 に答える