Mot*_*tti 35 c++ puzzle overloading function
我们都知道你可以根据参数重载一个函数:
int mul(int i, int j) { return i*j; }
std::string mul(char c, int n) { return std::string(n, c); }
Run Code Online (Sandbox Code Playgroud)
你能根据返回值重载一个函数吗?根据返回值的使用方式定义一个返回不同内容的函数:
int n = mul(6, 3); // n = 18
std::string s = mul(6, 3); // s = "666"
// Note that both invocations take the exact same parameters (same types)
Run Code Online (Sandbox Code Playgroud)
您可以假设第一个参数介于0-9之间,无需验证输入或进行任何错误处理.
pae*_*bal 50
您必须告诉编译器使用哪个版本.在C++中,您可以通过三种方式完成.
你有点作弊,因为你发送一个整数给一个等待char的函数,并且当'6'的char值不是6但是54(用ASCII)时错误地发送了数字6:
std::string mul(char c, int n) { return std::string(n, c); }
std::string s = mul(6, 3); // s = "666"
Run Code Online (Sandbox Code Playgroud)
当然,正确的解决方案是
std::string s = mul(static_cast<char>(54), 3); // s = "666"
Run Code Online (Sandbox Code Playgroud)
我想,这是值得一提的,即使你不想要解决方案.
您可以为每个函数添加一个伪参数,从而强制编译器选择正确的函数.最简单的方法是发送返回所需类型的NULL虚拟指针:
int mul(int *, int i, int j) { return i*j; }
std::string mul(std::string *, char c, int n) { return std::string(n, c); }
Run Code Online (Sandbox Code Playgroud)
哪个可以与代码一起使用:
int n = mul((int *) NULL, 6, 3); // n = 18
std::string s = mul((std::string *) NULL, 54, 3); // s = "666"
Run Code Online (Sandbox Code Playgroud)
使用此解决方案,我们创建一个"虚拟"函数,其代码在实例化时将无法编译:
template<typename T>
T mul(int i, int j)
{
// If you get a compile error, it's because you did not use
// one of the authorized template specializations
const int k = 25 ; k = 36 ;
}
Run Code Online (Sandbox Code Playgroud)
你会注意到这个函数不会编译,这是一件好事,因为我们只想通过模板特化来使用一些有限的函数:
template<>
int mul<int>(int i, int j)
{
return i * j ;
}
template<>
std::string mul<std::string>(int i, int j)
{
return std::string(j, static_cast<char>(i)) ;
}
Run Code Online (Sandbox Code Playgroud)
因此,以下代码将编译:
int n = mul<int>(6, 3); // n = 18
std::string s = mul<std::string>(54, 3); // s = "666"
Run Code Online (Sandbox Code Playgroud)
但是这个不会:
short n2 = mul<short>(6, 3); // error: assignment of read-only variable ‘k’
Run Code Online (Sandbox Code Playgroud)
嘿,你也骗了!
是的,我确实对两个"重载"函数使用了相同的参数.但你确实开始作弊(见上文)......
^ _ ^
更严重的是,如果您需要具有不同的参数,那么您将编写更多代码,然后在调用函数时必须明确使用正确的类型以避免歧义:
// For "int, int" calls
template<typename T>
T mul(int i, int j)
{
// If you get a compile error, it's because you did not use
// one of the authorized template specializations
const int k = 25 ; k = 36 ;
}
template<>
int mul<int>(int i, int j)
{
return i * j ;
}
// For "char, int" calls
template<typename T>
T mul(char i, int j)
{
// If you get a compile error, it's because you did not use
// one of the authorized template specializations
const int k = 25 ; k = 36 ;
}
template<>
std::string mul<std::string>(char i, int j)
{
return std::string(j, (char) i) ;
}
Run Code Online (Sandbox Code Playgroud)
这段代码将被用作:
int n = mul<int>(6, 3); // n = 18
std::string s = mul<std::string>('6', 3); // s = "666"
Run Code Online (Sandbox Code Playgroud)
并且以下行:
short n2 = mul<short>(6, 3); // n = 18
Run Code Online (Sandbox Code Playgroud)
仍然不会编译.
我喜欢C++ ......
:-P
Coi*_*oin 41
class mul
{
public:
mul(int p1, int p2)
{
param1 = p1;
param2 = p2;
}
operator int ()
{
return param1 * param2;
}
operator std::string ()
{
return std::string(param2, param1 + '0');
}
private:
int param1;
int param2;
};
Run Code Online (Sandbox Code Playgroud)
不是我会用它.
Ecl*_*pse 23
如果你想mul成为一个真正的函数而不是一个类,你可以使用一个中间类:
class StringOrInt
{
public:
StringOrInt(int p1, int p2)
{
param1 = p1;
param2 = p2;
}
operator int ()
{
return param1 * param2;
}
operator std::string ()
{
return std::string(param2, param1 + '0');
}
private:
int param1;
int param2;
};
StringOrInt mul(int p1, int p2)
{
return StringOrInt(p1, p2);
}
Run Code Online (Sandbox Code Playgroud)
这使您可以执行诸如将mul函数作为函数传递到std算法之类的操作:
int main(int argc, char* argv[])
{
vector<int> x;
x.push_back(3);
x.push_back(4);
x.push_back(5);
x.push_back(6);
vector<int> intDest(x.size());
transform(x.begin(), x.end(), intDest.begin(), bind1st(ptr_fun(&mul), 5));
// print 15 20 25 30
for (vector<int>::const_iterator i = intDest.begin(); i != intDest.end(); ++i)
cout << *i << " ";
cout << endl;
vector<string> stringDest(x.size());
transform(x.begin(), x.end(), stringDest.begin(), bind1st(ptr_fun(&mul), 5));
// print 555 5555 55555 555555
for (vector<string>::const_iterator i = stringDest.begin(); i != stringDest.end(); ++i)
cout << *i << " ";
cout << endl;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
MrZ*_*bra 21
没有.
您不能通过返回值重载,因为调用者可以对其执行任何操作(或不执行任何操作).考虑:
mul(1, 2);
返回值刚被丢弃,因此无法单独根据返回值选择重载.
在类之间使用隐式转换.
class BadIdea
{
public:
operator string() { return "silly"; }
operator int() { return 15; }
};
BadIdea mul(int, int)
Run Code Online (Sandbox Code Playgroud)
你得到了这个想法,虽然很可怕.