我有一个功能模板(c ++)
template<typename T>
void print_to_default_file(T &obj, ADDON addon = "")
和重载功能
template<typename T>
void print_to_default_file(T &obj, std::string objS) // or char* objS
类ADDON
具有以下签名的运算符重载
void operator=(const std::string)
问题是,当我这样做时 print_to_default_file(“test”,“我将去哪里”)
正在调用第一个,但我想调用第二个。我也厌倦了char *而不是std :: string但结果是一样的。
任何人都可以指出出了什么问题
ADDON简化版
class ADDON {
std::string s;
public:
ADDON() {
s = "";
}
ADDON(std::string in) {
s = in;
}
ADDON(const char in[]) {
s = in;
}
void operator=(const std::string in) {
s = in;
}
std::string getString() {
return s;
}
};
答案 0 :(得分:5)
您向我们展示的代码
#include <iostream>
#include <string>
class ADDON {
std::string s;
public:
ADDON() {
s = "";
}
ADDON(std::string in) {
s = in;
}
ADDON(const char in[]) {
s = in;
}
void operator=(const std::string in) {
s = in;
}
std::string getString() {
return s;
}
};
template<typename T>
void print_to_default_file(T &obj, ADDON addon = "")
{ std::cout << "first overload\n"; }
template<typename T>
void print_to_default_file(T &obj, std::string objS)
{ std::cout << "second overload\n"; }
int main()
{
print_to_default_file("test","where will I go");
}
无法编译(online output)并出现以下错误
prog.cpp:在函数'int main()'中:prog.cpp:39:52:错误:调用 重载'print_to_default_file(const char [5],const char [16])'是 模棱两可的prog.cpp:39:52:注意:候选人是:prog.cpp:30:6:注意: void print_to_default_file(T&amp;,ADDON)[with T = const char [5]] prog.cpp:34:6:注意:void print_to_default_file(T&amp;,std :: string)[with T = const char [5]; std :: string = std :: basic_string]
原因是名称查找和参数推断找到2个候选者:第一个重载需要const char*
到ADDON
转换,第二个重载需要const char*
到std::string
转换。两个转换序列都是同样好的匹配,过载资源不明确,程序也不正确。
只需更改第二个重载,将const char*
作为参数(而不是char*
,它不能绑定字符串文字),它将是原始字符串文字作为参数的最佳匹配
template<typename T>
void print_to_default_file(T &obj, const char* objS) // but NOT char* objS
{ std::cout << "second overload\n"; }
您现在将获得第二次重载(online output)。要选择第一个重载,只需在参数列表中调用ADDON
构造函数
int main()
{
print_to_default_file("test", ADDON("where will I go"));
}
请注意,这将调用ADDON(const char[])
构造函数而不是ADDON(std::string)
构造函数,因为后者需要用户定义的转换(online output)。
拥有非显式的单个参数构造函数是非常危险的。始终在这些功能周围使用explicit
关键字。
class ADDON {
std::string s;
public:
ADDON() {
s = "";
}
explicit ADDON(std::string in) {
s = in;
}
explicit ADDON(const char in[]) {
s = in;
}
void operator=(const std::string in) {
s = in;
}
std::string getString() {
return s;
}
};
这也会调用第二个重载(online output),因为ADDON
重载没有显式调用任何构造函数。要选择第一个重载,请再次调用参数列表中的ADDON
构造函数。