重载operator和modifiyng string

时间:2016-04-01 19:15:26

标签: c++ operator-overloading

我正在学习运营商重叠。我创建了一个简单的类来测试它。

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;
};

引发传递const字符串的错误。

我尝试使用

Beer operator + ( const string *a)const { 
       swap(this -> name , this -> name + " " + a);
       return *this;
    };

其中抱怨一个是cosnst字符串,而secon一个是基本字符串。

这个想法很简单。

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>)'|

// erro with string

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]|

3 个答案:

答案 0 :(得分:2)

评论:

  1. 不要包含整个std命名空间。你可能会用你自己的代码遇到令人讨厌的名字冲突。最多使用您明确需要的符号,例如using std::string;

  2. 除非您需要修改值的副本,否则通过const引用传递std::string之类的大对象。当您将参数声明为具有值类型std::string时,您会收到该字符串的副本,除非您需要在您的函数内部修改副本,否则这是非常昂贵的。

    这是C ++标准的一个长期存在的问题:这样的实现细节,应该与函数的用户无关,泄漏到接口(函数的声明)。尽管如此,当复制有意义时,让编译器给你一个而不必输入那么多。因此:

    // 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;
    }
    
  3. 使用初始化列表,您不需要做愚蠢的名称体操(您有onertwor名称:

    Beer(int one, int two, const std::string & name) :
      one(one),
      two(two),
      name(name)
    {}
    
  4. 声明只读访问器const:

    int getOne() const { return one; }
    
  5. 通过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
    
  6. +运算符中取一个字符串,您应该返回一个新对象,而不是修改this。你几乎应该按照其他操作员的方式做到这一点。

    Beer operator +(const std::string & a) const {
      return Beer(one, two, name + " " + a);
    };
    
  7. 如果您想修改对象,则需要operator +=

    Beer & operator+=(const std::string & a) {
      name += " ";
      name += a;
      return *this;
    }
    
  8. 即使您的课程旨在试验操作员,您也应该始终考虑操作员是否让生活更轻松。例如,您的班级有三名成员。除非从类的语义中清楚地看出,否则不会立即明白这些成员中的哪一个将被操作。例如,使用名为addToOneaddToTwoappendToName的方法代替运算符,或者只是让用户通过setter设置成员,会更清楚,比如setOne(int one) { this->one = one; }。然后,用户只需beer.setOne(beer.getOne() + 2);

  9. 考虑使用不带get前缀的getter命名,例如:

    class Beer {
      int m_one;
    public int one() const { reeturn m_one; }
    };
    

    用户输入的次数较少。标准库以及boostQt等大型库遵循此约定,例如您有std::string::size(),而非std::string::getSize()

答案 1 :(得分:1)

Beer operator + (string a)const {
  this -> name =  this -> name +" "+a;
};

你不应该改变调用+运算符的对象的内容,如果你执行A = B + C,则不应该改变B的内容。编译器正确地通知了你,因为它是一个const函数。

而是创建一个临时对象来保存'sum'并返回它。

Beer operator + (string a)const {
    return Beer(one, two, name + " " + a);  
};

答案 2 :(得分:0)

operator+()此处:

Beer operator+( string a ) const 
{
    this->name = this->name + " " + a;
};

函数签名上的const是编译器的保证,当调用函数时,您不会更改对象中的数据,但是您更改了对象中的数据。