21xrx.com
2024-09-20 00:45:45 Friday
登录
文章检索 我的文章 写文章
C++中的运算符重载:详解
2023-07-01 15:56:41 深夜i     --     --
运算符重载 C++ 编程语言 详解 重载函数 操作符函数

C++可以对内置类型或用户自定义类型进行运算符重载,使得这些类型能够像内置类型一样支持运算符操作。这种机制可以让代码更加简洁清晰,并且更符合实际的运算规则。本文将详解C++中运算符重载的相关知识。

一、基本概念

1. 运算符重载:对已有的运算符重新定义,使得它们能够用于用户自定义类型。

2. 运算符函数:重载后的运算符实际上是对应的函数,这种函数称为运算符函数。

3. 运算符函数的形式:操作符关键字operator后跟运算符的符号,例如:operator+(),operator-()。

二、运算符的重载方法

运算符有两种重载方法:

1. 成员函数重载

这种方法是将运算符作为类的成员函数进行重载,运算符函数有一个隐含的this指针,指向调用对象。所以对于类类型的运算符重载,一般都采用成员函数重载,例如:

class Vec {

public:

  Vec(int x = 0, int y = 0) : x(x), y(y) {}

  Vec& operator+=(const Vec& rhs) {

    x += rhs.x;

    y += rhs.y;

    return *this;

  }

  int x, y;

};

int main() {

  Vec a(1, 2);

  Vec b(2, 3);

  a += b;   // 等价于a.operator+=(b);

  return 0;

}

2. 非成员函数重载

这种方法是将运算符作为普通函数进行重载,函数有两个参数,分别为左、右运算对象。一般情况下,采用非成员函数重载,如果需要访问类的私有成员,则需要将函数声明为类的友元函数,例如:

class Vec {

public:

  Vec(int x = 0, int y = 0) : x(x), y(y) {}

  friend Vec operator+(const Vec& lhs, const Vec& rhs) {

    Vec ret(lhs);

    ret += rhs;

    return ret;

  }

  int x, y;

};

int main() {

  Vec a(1, 2);

  Vec b(2, 3);

  Vec c = a + b;  // 等价于operator+(a, b);

  return 0;

}

三、适用范围

C++中既可以重载内置类型的运算符,也可以重载用户自定义类型的运算符。但是,对于内置类型的运算符重载,只能够采用非成员函数重载的方法,例如:

int operator+(int a, int b)

  return a - b;

int main() {

  int a = 3;

  int b = 2;

  int c = a + b;  // 等价于operator+(a, b);

  return 0;

}

对于某些运算符,例如赋值运算符和下标运算符,只能够重载为类的成员函数,例如:

class Array {

public:

  int& operator[](int idx) { return data[idx]; }

  Array& operator=(const Array& rhs) {

    data = rhs.data;

    return *this;

  }

  std::vector data;

};

int main() {

  Array a, b;

  a[0] = 1;  // 等价于a.operator[](0) = 1;

  b = a;   // 等价于b.operator=(a);

  return 0;

}

四、运算符的特殊重载

1. 后置递增、递减运算符:一般重载为成员函数。

2. 函数调用运算符:一般重载为成员函数,其返回值代表函数的执行结果。

3. 类型转换运算符:一般重载为成员函数,用于将类转换为内置类型或其他类。

五、运算符重载的注意事项

1. 运算符的优先级不会受到重载的影响,例如a+b*c,在遇到+之前,会先计算b*c,无论是+被重载为成员函数还是非成员函数。

2. 不能重载的运算符包括:成员访问运算符“.”、“->”、条件运算符“?:”、sizeof、typeid等。

3. 不要滥用运算符重载,应该只在有必要的情况下使用。

总之,运算符重载是C++的一项重要的特性,合理使用可以使代码更加简洁、清晰,提高程序的效率和可维护性。但是在实际使用中需要注意一些比较容易出现的问题,例如优先级问题以及类型转换问题等。

  
  

评论区

{{item['qq_nickname']}}
()
回复
回复