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 中
最伟大的是 A、B、C 中最伟大的是 A

问题 :

如果我在 Max 函数 A、B、C 中传递 char 数据类型,它返回 C,但如果我传递字符串数据类型 A、B、C,它返回 A。

为什么它在这里返回 A?

4

4 回答 4

4

这里有两个问题。其他两个答案已经描述了您的第三个电话的问题。

但你的第二个电话也是错误的:

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

这应该会产生未定义的行为,因为strcmp需要以零结尾的字符串,但这不是您输入函数的内容。相反,您将它传递给单个char值的指针,并且strcmp完全有权对此感到窒息。基本上,任何事情都可能发生,而您的代码可以正常工作纯属偶然。

调用这个重载的正确方法是传递chars,或者传递 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

在第一种情况下,它使用模板特化,在第二种情况下,使用通用模板。

但是您的问题是您Max在第二种情况下的调用方式:

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

另外,我建议constchar*专业化中使用指针,因为就目前而言,除了非常量指针之外,你不能传递任何东西,这并不完全是常见的情况。

于 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()));

但由于您使用的是strings,请注意您可以简单地将它们与 == < > 等进行比较。

于 2010-10-12T08:43:17.800 回答