我正在学习运算符重叠。我创建了简单的类来测试它。
class Beer{
public:
Beer(int oner , int twor , string name){
this -> one = oner;
this -> two = twor;
this -> name = name;
};
int getOne(){
return this -> one;
};
int getTwo(){
return this -> two;
};
string getName(){
return this -> name;
};
Beer operator + (const Beer &a)const {
return Beer(5,two+a.two,"firstName");
};
Beer operator + (string a)const {
this -> name = this -> name +" "+a;
};
private:
int one;
int two;
string name;
};
我想弄清楚,如何使用重载的操作数来中化字符串。我声明的函数
Beer operator + (string a)const {
this -> name = this -> name +" "+a;
};
抛出有关传递常量字符串的错误。
我试过用
Beer operator + ( const string *a)const {
swap(this -> name , this -> name + " " + a);
return *this;
};
其中一个是 cosnst string ,第二个是 basic string。
这个想法很简单。
Beer one ( 5, 6, "one")
one + "two"
// one.name = "one two"
正确的做法是什么?
//交换错误
error: no matching function for call to 'swap(const string&, std::basic_string<char>)'|
//字符串错误
passing 'const string {aka const std::basic_string<char>}' as 'this' argument of 'std::basic_string<_CharT, _Traits, _Alloc>& std::basic_string<_CharT, _Traits, _Alloc>::operator=(std::basic_string<_CharT, _Traits, _Alloc>&&) [with _CharT = char; _Traits = std::char_traits<char>; _Alloc = std::allocator<char>]' discards qualifiers [-fpermissive]|
最佳答案
评论:
不要包含整个
std
命名空间。您可能会遇到与您自己的代码发生严重名称冲突的情况。最多,使用您明确需要的符号,例如使用 std::string;
。除非您需要修改一个值的拷贝,否则通过 const 引用传递大型对象,例如
std::string
。当您将一个参数声明为具有值类型std::string
时,您会收到该字符串的一个拷贝,除非您需要一个拷贝来在您的函数内部进行修改,否则这是昂贵的。这是 C++ 标准的一个长期存在的问题:像这样的实现细节,应该与函数的用户无关,泄漏到接口(interface)(函数的声明)中。尽管如此,当有一份拷贝有意义时,让编译器给你一份,而不必输入那么多。因此:
// prefer this std::string fooize(std::string foo) { assert(foo.size() > 0); foo.insert(1, "foo"); return foo; } // over this std::string fooize(const std::string & bar) { assert(bar.size() > 0); auto foo = bar; foo.insert(1, "foo"); return foo; }
使用一个初始化列表,你就不需要做愚蠢的名字体操了(你有
一个
,两个
的名字:Beer(int one, int two, const std::string & name) : one(one), two(two), name(name) {}
声明只读访问器 const:
int getOne() const { return one; }
通过 const 引用返回像字符串这样的大值;用户代码可能会让编译器在需要时自动帮助制作拷贝:
const std::string & getName() const { return name; } // use: Beer beer{0,0,""}; std::cout << (beer.getName() + "!") << std::endl; // makes a copy of name as needed
在
+
运算符中接受一个字符串,您应该返回一个新对象,而不是修改this
。您几乎应该像其他运算符(operator)那样做 + 您已经做到了。Beer operator +(const std::string & a) const { return Beer(one, two, name + " " + a); };
如果你想修改你的对象,你需要
operator +=
:Beer & operator+=(const std::string & a) { name += " "; name += a; return *this; }
即使您的类(class)旨在试验运算符,您也应该始终考虑运算符是否让生活更轻松。例如,您的类(class)有三个成员。除非从类的语义中清楚地看出,否则这些成员中的哪些将被操作并不是很明显。将方法命名为
addToOne
、addToTwo
和appendToName
会更清晰,例如,而不是运算符,或者只是让用户通过 setter 设置成员,例如setOne(int one) { this->one = one; }
。然后用户只需执行beer.setOne(beer.getOne() + 2);
。考虑在没有
get
前缀的情况下命名 getter,例如class Beer { int m_one; public int one() const { reeturn m_one; } };
它减少了用户的输入。标准库以及像
boost
和Qt
这样的大型库都遵循这个约定,例如你有std::string::size()
,而不是std::string::getSize()
等
关于c++ - 重载运算符和修改字符串,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36364191/