4

私の教授は私にこの任務を与えてくれました。

Maxと呼ばれるジェネリック関数を実装します。これはジェネリック型の3つの引数を取り、これらの3つから最大値を返します。char*型に特化した関数を実装します。

これが私のコードです:

#include <iostream>
#include <string>

using namespace std;

template<typename T>
T Max(T first,T second,T third )
{
    if(first > second)
    {
        if(first > third)
        {
            return first;
        }
        else
        {
            return third;
        }
    }
    else if(second > third)
    {
        return second;
    }
    else
    {
        return third;
    }
}


template<>
char* Max(char* first,char* second,char* third)
{   
    if(strcmp(first, second) > 0)
    {
        if(strcmp(first, third) > 0)
        {
            return first;
        }
        else
        {
            return third;
        }
    }
    else if(strcmp(second, third) > 0)
    {
        return second;
    }
    else
    {
        return third;
    }
}

int main(void)
{
    cout << "Greatest in 10, 20, 30 is " << Max(10, 20, 30) << endl;

    char a = 'A';
    char b = 'B';
    char c = 'C';
    char Cptr = *Max(&a, &b, &c);
    cout << "Greatest in A, B ,C is " << Cptr << endl;

    string d = "A";
    string e = "B";
    string f = "C";
    string result = *Max(&d, &e, &f);

    cout << "Greatest in A, B, C is " << result << endl;
}

出力:

10、20、30で最大は30
A、B、Cで最大はCで
最大A、B、CはAで最大

問題 :

Max関数A、B、Cでcharデータ型を渡すと、Cが返されますが、文字列データ型A、B、Cを渡すと、Aが返されます。

なぜここにAが返されるのですか?

4

4 に答える 4

4

ここには2つの問題があります。他の2つの回答は、3回目の呼び出しの問題をすでに説明しています。

しかし、2回目の呼び出しも間違っています。

char a = 'A';
char b = 'B';
char c = 'C';
char Cptr = *Max(&a, &b, &c);

strcmpゼロで終了する文字列を想定しているため、これは未定義の動作を生成するはずですが、これは関数にフィードするものではありません。charむしろ、あなたはそれに個々の値へのポインタを渡しておりstrcmp、これを窒息させるあらゆる権利を持っています。基本的に、何が起こる可能性があり、コードが機能するのは純粋なチャンスです。

このオーバーロードを呼び出す正しい方法はchar、sを渡すか、Cスタイルの文字列を渡すことです。

char C = Max(a, b, c);

// or:
char as[] = "a";
char bs[] = "b";
char cd[] = "c";
char* result = Max(as, bs, cd);

または、文字列リテラルを直接渡すこともできます。

最後に、スタイルについてのメモ。着信文字列を適切なsに変換し、次の汎用バージョンを再利用することchar*で、少し「ごまかす」と、特殊化を大幅に短縮できます。char*std::stringMax

template<>
char* Max(char* first,char* second,char* third)
{
    return Max(string(first), string(second), string(third));
}

(確かに、これはおそらく効率が悪いですが、ほとんどの場合、これは安全に無視できます。)

そして、さらに別の注意:割り当てはchar*、あなたの答えが正しいように、関数テンプレートを特殊化するように明示的に要求しました。ただし、別の方法は、関数を特殊化するのではなく、関数をオーバーロードすることです。(クラステンプレートとは対照的に)関数テンプレートの場合、これは、テンプレート引数をさらに必要としない場合の通常の方法です。

char* Max(char* first,char* second,char* third)
{
    return Max(string(first), string(second), string(third));
}

唯一の違いはtemplate <>、関数ヘッダーの前にないことです。

于 2010-10-12T08:47:00.003 に答える
2
string result = *Max(&d, &e, &f);

この行はあなたの問題です。文字列へのポインターを渡しているため、実際には最高のポインターアドレスが返されます。

スタックは下に向かって成長するため、スタックの開始アドレスが最高になることに注意してください。後続の各スタック割り当て (つまり、この場合の変数宣言) は、徐々に低いスタック アドレスを開始するため、"A" が最大値として表示されます。

これを書くと:

string result = Max(d, e, f);

期待通りの答えが返ってきます。

于 2010-10-12T08:39:07.887 に答える
2

最初のケースではテンプレートの特殊化を使用し、2 番目のケースでは汎用テンプレートを使用します。

しかし、あなたの問題はMax、2番目のケースで呼び出す方法です:

string d = "A";
string e = "B";
string f = "C";
// you're comparing the string addresses here, not their content
string result = *Max(&d, &e, &f); 

次のようにする必要があります。

string d = "A";
string e = "B";
string f = "C";
string result = Max(d, e, f);

また、特殊化constでポインターを使用することをお勧めしますchar*。現状では、正確には一般的なケースではない非 const ポインター以外は何も渡すことができないためです。

于 2010-10-12T08:40:34.567 に答える
1

それ以外の

string result = *Max(*&d, &e, &f)

あなたが必要

string result = Max(d.c_str(), e.c_str(), f.c_str())

const char*これは、関数が をとり、 をとらない場合に機能することに注意してくださいchar*。間違っている char* の使用を主張する場合は、constness をキャストする必要があります。

 string result = Max(const_cast<char*>(d.c_str()),

 const_cast<char*>(e.c_str()), const_cast<char*>(f.c_str()));

ただし、s を使用しているstringため、単純に == < > などで比較できることに注意してください。

于 2010-10-12T08:43:17.800 に答える