我的教授给了我这个任务。
实现一个名为的泛型函数 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是 甲
问题:
如果我在Max函数A,B,C中传递char数据类型,它将返回C,但如果我传递字符串数据类型A,B,C,则返回A.
为什么在这里返回A?
答案 0 :(得分:4)
这里有两个问题。其他两个答案已经描述了第三次电话会议的问题。
但你的第二次电话也错了:
char a = 'A';
char b = 'B';
char c = 'C';
char Cptr = *Max(&a, &b, &c);
这会产生未定义的行为,因为strcmp
期望以零结尾的字符串,但这不是您输入函数的内容。相反,您将指针传递给单个char
值,而strcmp
则有权对此进行扼杀。基本上,任何事情都可能发生,而且你的代码工作是纯粹的机会。
调用此重载的正确方法是传递char
或传递C风格的字符串:
char C = Max(a, b, c);
// or:
char as[] = "a";
char bs[] = "b";
char cd[] = "c";
char* result = Max(as, bs, cd);
或者,您可以直接传递字符串文字。
最后,关于风格的说明。如果您通过将传入的char*
字符串转换为正确的char*
并重新使用std::string
的通用版本来“欺骗”一点,那么Max
专业化可以大大缩短:
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 <>
。
答案 1 :(得分:2)
string result = *Max(&d, &e, &f);
此行是您的问题。您正在将指针传递给字符串,因此它实际上返回了最高的指针地址。
请记住堆栈向下增长,因此堆栈的开头具有最高地址。每个后续堆栈分配(即本例中的变量声明)将开始逐渐降低堆栈地址,因此“A”显示为最大值。
如果你这样写:
string result = Max(d, e, f);
你会得到你期望的答案。
答案 2 :(得分: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);
另外,我建议在const
专门化中使用char*
指针,因为就目前而言,除了非常量指针之外,你不能传递任何东西,这不是常见的情况。
答案 3 :(得分: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()));
但由于您使用的是string
,请注意您只需将它们与==&lt;进行比较即可。 &GT;等