c++ - 重载运算符和修改字符串

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

抛出有关传递常量字符串的错误。

我试过用

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

最佳答案

评论:

  1. 不要包含整个 std 命名空间。您可能会遇到与您自己的代码发生严重名称冲突的情况。最多,使用您明确需要的符号,例如使用 std::string;

  2. 除非您需要修改一个值的拷贝,否则通过 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;
    }
    
  3. 使用一个初始化列表,你就不需要做愚蠢的名字体操了(你有一个两个的名字:

    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。您几乎应该像其他运算符(operator)那样做 + 您已经做到了。

    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. 即使您的类(class)旨在试验运算符,您也应该始终考虑运算符是否让生活更轻松。例如,您的类(class)有三个成员。除非从类的语义中清楚地看出,否则这些成员中的哪些将被操作并不是很明显。将方法命名为 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()

关于c++ - 重载运算符和修改字符串,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36364191/

相关文章:

c++ - Linux 汇编程序消息错误 c++

C++ 替代函数

c++ - 带有 std::function 参数的重载运算符

c++ - 我应该使用哪种 C++ 运算符重载变体?而且,为什么?

c++ - 重载括号运算符作为成员函数

c++ - 这是否过于聪明或不安全?

c++ - 如何使用 NDIS_SUPPORT_NDIS630 将 NDIS 6.2 移植到 NDIS 6.3?

c++ - shared_ptr 的对象池模式是否可能?

c++ - 定义和声明中的内联

c++ - 在 C++ 中使用模板类为容器类型重载 'opeator<<'