运算符重载

C++提供了运算符重载的功能,对于我们自定义的类,使用运算符重载能够简化对像的操作。举例来说,C++标准库的std::string其实就使用了运算符重载功能,因此我们才能对其使用+==等操作。C++中除了.::.*:?sizeof,其余运算符都是可重载的,不过有些运算符的重载我们其实很少使用,比如重载newdelete运算符就非常罕见,这可能给使用者造成困惑。

运算符重载一直是个有巨大争议的特性,Java完全没有运算符重载,但是其类库却无比庞大而且非常易用,可见运算符重载也并不是非用不可。不过C++中适当的使用运算符重载确实能够简化代码,可见这个功能也有其存在意义。这里我们介绍几个简单的运算符重载。

运算符重载的规则

运算符重载遵循以下规则:

  • 不能改变操作符的优先级和结合性
  • 不能改变操作符的操作数
  • 不能创建新的操作符,只能重载C++中已有的操作符,有些操作符不能重载

实现运算符重载

下面例子重载了=操作符,允许直接将字符串字面值赋值给我们自定义的mystring类。

#include <cstring>
#include <iostream>

class mystring {
private:
  char *s;

public:
  mystring() { this->s = new char[1024]; }

  mystring(const mystring &it) {
    this->s = new char[1024];
    strcpy(this->s, it.s);
  }

  void operator=(const char *s) { strcpy(this->s, s); }

  void print() { std::cout << this->s << std::endl; }

  ~mystring() { delete[] this->s; }
};

int main() {
  mystring s1;
  s1 = "hello, world!";
  mystring s2 = s1;
  s2.print();

  return 0;
}

这里重载操作符的写法就是void operator =(const char *s){},和定义一个函数差不多,其中的operator =其实就相当于函数名。至于代码中mystring s2 = s1执行的其实是拷贝构造函数,它被定义为mystring(const mystring &it){},这里=原来的意义并没有改变,因为其参数类型是mystring &而不是const char *

下面例子重载了+运算符,实现了mystring之间相加、mystring和字符串字面值相加、字符串字面值和mystring相加三种功能。

#include <cstring>
#include <iostream>

class mystring {
private:
  char *s;

public:
  mystring() { this->s = new char[1024]; }

  mystring(const char *s) {
    this->s = new char[1024];
    strcpy(this->s, s);
  }

  mystring(const mystring &it) {
    this->s = new char[1024];
    strcpy(this->s, it.s);
  }

  mystring operator+(mystring &it) {
    char buf[1024];
    strcpy(buf, this->s);
    strcat(buf, it.s);
    return buf;
  }

  mystring operator+(const char *s) {
    char buf[1024];
    strcpy(buf, this->s);
    strcat(buf, s);
    return buf;
  }

  void print() { std::cout << this->s << std::endl; }

  ~mystring() { delete[] this->s; }

  friend mystring operator+(const char *s, const mystring &m);
};

mystring operator+(const char *s, const mystring &m) {
  char buf[1024];
  strcpy(buf, m.s);
  strcat(buf, s);
  return buf;
}

int main() {
  mystring s1("hello");
  mystring s2("world");

  mystring s3 = s1 + s2;
  s3.print();

  mystring s4 = s1 + "aaa";
  s4.print();

  mystring s5 = "bbb" + s2;
  s5.print();

  return 0;
}

注意mystring operator +(const char *s, const mystring &m)这个是定义在类的外面的,但是它需要访问类内部的成员,因此类中声明了该函数为友元。

下面例子重载了==操作符。

#include <cstring>
#include <iostream>

class mystring {
private:
  char *s;

public:
  mystring() { this->s = new char[1024]; }

  mystring(const char *s) {
    this->s = new char[1024];
    strcpy(this->s, s);
  }

  mystring(const mystring &it) {
    this->s = new char[1024];
    strcpy(this->s, it.s);
  }

  bool operator==(const mystring &it) {
    if (strcmp(this->s, it.s) == 0) {
      return true;
    } else {
      return false;
    }
  }

  void print() { std::cout << this->s << std::endl; }

  ~mystring() { delete[] this->s; }

  friend bool operator==(const mystring &s1, const mystring &s2);
};

bool operator==(const mystring &s1, const mystring &s2) {
  if (strcmp(s1.s, s2.s) == 0) {
    return true;
  } else {
    return false;
  }
}

int main() {
  mystring s1("hello");
  mystring s2("hello");

  if (s1 == s2) {
    std::cout << "true" << std::endl;
  } else {
    std::cout << "false" << std::endl;
  }

  return 0;
}

+的写法基本是相同的,注意重载==要求返回值是bool类型,这符合==的语意。

作者:Gacfox
版权声明:本网站为非盈利性质,文章如非特殊说明均为原创,版权遵循知识共享协议CC BY-NC-ND 4.0进行授权,转载必须署名,禁止用于商业目的或演绎修改后转载。
Copyright © 2017-2024 Gacfox All Rights Reserved.
Build with NextJS | Sitemap