我想要做的是,允许使用setter函数传递指针,引用或常量引用:
class A{
std::string * p;
std::string st;
public:
A():p(0)
{}
A& setS(const std::string& s){
std::cout<<"called with const std::string&\n";
st = s;
p = &st;
return *this;
}
A& setS(std::string& s) {
std::cout<<"called with std::string&\n";
p = &s;
return *this;
}
A& setS(std::string* s) {
std::cout<<"called with std::string*\n";
p = s;
return *this;
}
};
int main(){
std::string s;
A a;
a.setS(std::move(s)) //const std::string&
.setS("") //const std::string&
.setS(s) //std::string&
.setS(0); //std::string*
//if std::string* version is not defined,
//setS(0) calls the const std::string& version and throws exception
return 0;
}
但我已经看到,如果指针版本不存在,setS(0)
会调用const std::string&
函数的setS()
版本。
指针和参考版本之间是否存在任何歧义,或者其他任何重要问题之间是否存在歧义?它是否定义良好并且预期在所有编译器中以相同的方式工作?
答案 0 :(得分:3)
没有歧义。如果在重载集中有A& setS(std::string* s)
,则setS(0)
调用指针版本,0
是空指针。这将是setS(nullptr)
的平等。
当A& setS(std::string* s)
不在重载集中时,编译器会查看是否有一种方法可以从0
构造临时字符串,然后将其传递给A& setS(const std::string& s)
,因为const&
可以绑定到临时的。 std::string
可以从单个指针构造,并再次0
作为空指针。因此,您将获得一个临时空指针,std::string
传递给const&
函数。
但这是未定义的行为。 std::string
的构造函数要求传递给它的指针是一个空终止的c字符串。如果不是,则行为未定义。
答案 1 :(得分:0)
当您删除setS
函数的指针重载时,您调用const std::string&
版本的原因是one of the std::string
constructors。
basic_string( const CharT* s,
const Allocator& alloc = Allocator() );
因此0
被视为NULL
,并被解释为const char*
,可以从中构建std::string
。 const&
能够延长左值的生命周期,因此可以将其传递到setS
的重载中。