C++运算符重载 C++中运算符重载详解及其作用介绍
我是小白呀 人气:0概述
运算符重载 (Operator Overloading)
函数重载
重载: 将同一名字重新赋予新的含义.
函数重载: 对一个函数赋予新的含义, 使之实现新功能. 例如:
int max(int x, int y); double max(double a, double b, double c);
运算符也有重载: 赋予运算符新的含义, 使之一名多用. 例如
int main() { int i = 2, j = 3; int k = i + j; string s1 = "good ", s2 = "morning"; string s3 = s1 + s2; cout << k << endl; cout << s3 << endl; return 0; }
输出结果:
5
good morning
运算符重载
通过运算符重载, 扩大了 C++ 已有运算符的作用, 使运算符能用于类对象. 使用运算符重载, 能使程序易于编写, 阅读和维护. 运算符被重载后, 其原有的功能仍然保留, 没有丧失过改变.
运算符重载实质上是函数的重载:
- 定义一个重载运算符的函数
- 需要执行被重载的运算符时, 系统就自动调用该函数, 以实现相应的运算
C++ 的运算符
- 算数运算符: +(加) -(减) *(乘) %(整除余数) ++(自加) – (自减)
- 关系运算符: >(大于) <(小于) ==(等于) >=(大于等于) <=(小于等于) !=(不等于)
- 逻辑运算符: &&(逻辑与) ||(逻辑或) !(逻辑非)
- 位运算符: <<(按位左移) >>(按位右移) &(按位与) |(按位或) ∧(按位异或) ~(按位取反)
- 赋值运算符: = 及其扩展赋值运算符
- 条件运算符: ?:
- 都好运算符: ,
- 指针运算符: *
- 引用运算符合地址运算符: &
- 求字节数运算符: sizeof
- 强制类型转换运算符: (类型) 或 类型()
- 成员运算符: .
- 指向成员的运算符:->
- 下标运算符: []
- 其他: 如函数调用运算符 ()
重载运算符的规则
- 不允许创造新的运算符, 只能对已有 C++ 运算符进行重载.
- C++ 允许重载运算符: 成员运算符(.), 成员指针访问运算符(.*), 域运算符(:😃, 求字节数运算符(sizeof), 条件运算符(?😃
- 重载不能改变运算符运算对象 (即操作数) 的个数
- 重载不能改变运算符的优先级别
- 重载不能改变运算符的结合性
- 重载运算符的函数不能有默认的参数
- 重载的运算符必须和用户定义的自定义类型的对象一起使用. 参数至少有一个是类对象或其 引用
成员函数实现 Complex 加法
Complex 类:
#ifndef PROJECT2_COMPLEX_H #define PROJECT2_COMPLEX_H class Complex { private: double real; double imag; public: Complex(); Complex(double r, double i); Complex add(Complex &c2); void display(); }; #endif //PROJECT2_COMPLEX_H
Complex.cpp:
#include <iostream> #include "Complex.h" using namespace std; Complex::Complex() : real(0), imag(0) {} Complex::Complex(double r, double i) : real(r), imag(i) {} Complex Complex::add(Complex &c2) { Complex c; c.real = real + c2.real; c.imag = imag + c2.imag; return c; } void Complex::display() { cout << "(" << real << ", "; cout << imag << "i)" << endl; }
main:
int main() { Complex c1(3, 4), c2(5, -10), c3; cout << "c1 ="; c1.display(); cout << "c2 ="; c2.display(); c3 = c1.add(c2); cout << "c1 + c2 = "; c3.display(); return 0; }
输出结果:
c1 =(3, 4i)
c2 =(5, -10i)
c1 + c2 = (8, -6i)
运算符重载的方法
运算符重载格式:
函数类型 operator 运算符名称 (形参流标) {对运算符的重载处理}
Complex 类:
#ifndef PROJECT4_COMPLEX_H #define PROJECT4_COMPLEX_H class Complex { private: double real; double imag; public: Complex(); Complex(double, double); void display(); Complex operator+(Complex &c2); }; #endif //PROJECT4_COMPLEX_H
Complex.cpp:
#include <iostream> #include "Complex.h" using namespace std; Complex::Complex() : real(0), imag(0) {} Complex::Complex(double r, double i) :real(r), imag(i) {} void Complex::display() { cout << "(" << real << ", "; cout << imag << "i)" << endl; } Complex Complex::operator+(Complex &c2) { Complex c; c.real = real + c2.real; c.imag = imag + c2.imag; return c; }
main:
#include <iostream> #include "Complex.h" using namespace std; int main() { Complex c1(3, 4), c2(5, -10), c3; cout << "c1 ="; c1.display(); cout << "c2 ="; c2.display(); c3 = c1 + c2; cout << "c1 + c2 = "; c3.display(); return 0; }
输出结果:
c1 =(3, 4i)
c2 =(5, -10i)
c3= (8, -6i)
多种实现方法
成员函数实现:
Complex Complex::operator+(Complex &c2) { Complex c; c.real = real + c2.real; c.imag = imag + c2.imag; return c; }
简化:
Complex Complex::operator+(Complex &c2){ return Complex(real +c2.real, imag + c2.image); }
友元函数实现:
Complex operator+(Complex &c1, Complex &c2){ ...... }
实现 operator+=
Complex 类:
#ifndef PROJECT4_COMPLEX_H #define PROJECT4_COMPLEX_H class Complex { private: double real; double imag; public: Complex(); Complex(double, double); void display(); Complex operator+=(const Complex &c); }; #endif //PROJECT4_COMPLEX_H
Complex.cpp:
#include <iostream> #include "Complex.h" using namespace std; Complex::Complex() : real(0), imag(0) {} Complex::Complex(double r, double i) :real(r), imag(i) {} void Complex::display() { cout << "(" << real << ", "; cout << imag << "i)" << endl; } Complex Complex::operator+=(const Complex &c) { real += c.real; // this->real += c.real; imag += c.imag; // this->imag += c.imag; return *this; }
main:
#include <iostream> #include "Complex.h" using namespace std; int main() { Complex c1(3, 4), c2(5, -10), c3; cout << "c1 ="; c1.display(); cout << "c2 ="; c2.display(); c1 += c2; cout << "c1= "; c1.display(); return 0; }
输出结果:
c1 =(3, 4i)
c2 =(5, -10i)
c1= (8, -6i)
三种运算符重载函数
运算符重载函数可以是类的成员函数:
- 它可以通过 this 指针自由地访问本类的数据成员. 少写一个函数的参数, 但有要求.
运算符重载函数可以是类的友元函数:
- 如果运算符左侧的操作属于 C++ 标准类型 (如 int) 或是一个其他类的对象, 则运算符重载函数不能选用成员函数. 为方便访问类的私有成员, 声明为友元函数为佳.
运算符重载函数还可以是普通函数:
- 只有极少的情况下才使用 (因普通函数一般不能直接访问类的私有成员)
成员函数实现
Complex 类:
#ifndef PROJECT4_COMPLEX_H #define PROJECT4_COMPLEX_H class Complex { private: double real; double imag; public: Complex(); Complex(double, double); void display(); Complex operator+(double d); // 成员函数实现 }; #endif //PROJECT4_COMPLEX_H
Complex.cpp:
#include <iostream> #include "Complex.h" using namespace std; Complex::Complex() : real(0), imag(0) {} Complex::Complex(double r, double i) :real(r), imag(i) {} void Complex::display() { cout << "(" << real << ", "; cout << imag << "i)" << endl; } Complex Complex::operator+(double d) { return Complex(real + d, imag); }
友元函数实现
Complex 类:
#ifndef PROJECT4_COMPLEX_H #define PROJECT4_COMPLEX_H class Complex { private: double real; double imag; public: Complex(); Complex(double, double); void display(); friend Complex operator+(Complex &c, double d); // 友元函数 }; #endif //PROJECT4_COMPLEX_H
Complex.cpp:
#include <iostream> #include "Complex.h" using namespace std; Complex::Complex() : real(0), imag(0) {} Complex::Complex(double r, double i) :real(r), imag(i) {} void Complex::display() { cout << "(" << real << ", "; cout << imag << "i)" << endl; } Complex operator+(Complex &c, double d) { return Complex(c.real + d, c.imag); }
输出结果
main:
#include <iostream> #include "Complex.h" using namespace std; int main() { Complex c1(3, 4), c2(5, -10), c3, c4; cout << "c1 ="; c1.display(); cout << "c2 ="; c2.display(); c3 = c1 + 3.14; cout << "c3= "; c3.display(); return 0; }
输出结果:
c1 =(3, 4i)
c2 =(5, -10i)
c3= (6.14, 4i)
重载单元运算符
单元运算符 (unary operation), 即只有一个运算量. 如: !a, -b, &c, *p, ++i, i-- 等.
例子
重载单元运算符实现分数对象的相反数.
Fraction 类:
#ifndef PROJECT4_FRACTION_H #define PROJECT4_FRACTION_H #include <iostream> using namespace std; class Fraction { private: int nume; // 分子 int deno; // 分母 public: Fraction(); Fraction(int, int); Fraction operator-(const Fraction &c); // 分数相减 Fraction operator-(); // 取反一目运算 friend ostream& operator<<(ostream &output, const Fraction &f); }; #endif //PROJECT4_FRACTION_H
Fraction.cpp:
#include "Fraction.h" Fraction::Fraction() : nume(0), deno(0) {} Fraction::Fraction(int n , int d) : nume(n), deno(d) {} Fraction Fraction::operator-(const Fraction &c) { return Fraction(nume*c.deno - c.nume*deno, deno*c.deno); } Fraction Fraction::operator-() { return Fraction(-nume, deno); } ostream& operator<<(ostream &output, const Fraction &f) { double result = (double)f.nume / f.deno; output << result << endl; return output; }
main:
#include <iostream> #include "Fraction.h" using namespace std; int main() { Fraction f1(1,3), f2(1,5), f3, f4; f3 = f1 - f2; // 分数相减 f4 = -f1; // 分数取反 cout << f3; cout << f4; return 0; }
输出结果:
0.133333
-0.333333
重载二元运算符
二元运算符 (binary operation).
- 有两个操作数, 通常在运算符的左右两侧 (例如: 3+2, 5>8, x*=3)
- 重载双目运算符时, 函数中应该有两个参数
例子
要求:
- 定义字符串类 String, 用来存放不定长的字符串
- 重载关系运算符, 用于两个字符串的比较运算
步骤:
- 定义类的 “框架”
- 完善运算符重载
String 类:
#ifndef PROJECT4_STRING_H #define PROJECT4_STRING_H #include <cstdlib> class String { private: char *p; public: String(){p=nullptr;} String(char *str); void display(); }; #endif //PROJECT4_STRING_H
String.cpp:
#include <iostream> #include <cstring> #include "String.h" using namespace std; String::String(char *str) { p = new char[sizeof(str)]; strcpy(p, str); } void String::display() { cout << p; }
main:
#include <iostream> #include "String.h" using namespace std; int main() { String s1("Hello"); String s2("China"); s1.display( ); cout<<" "; s2.display( ); cout<<endl; return 0; }
输出结果:
Hello China
重载 I/O
通过重载输入流 (input stream) 和输出流 (output stream), 我们可以用来输出用户自己定义的数据.
格式:
ostream &operator<<(ostream&, const 自定义类&); istream &operator>>(istream&,自定义类&);
插入运算符 <<
Complex 类:
#ifndef PROJECT4_COMPLEX_H #define PROJECT4_COMPLEX_H #include <iostream> using namespace std; class Complex { private: double real; double imag; public: Complex(); Complex(double, double); void display(); Complex operator+(Complex &c); friend ostream& operator<<(ostream &output, const Complex &c); }; #endif //PROJECT4_COMPLEX_H
Complex.cpp:
#include <iostream> #include "Complex.h" using namespace std; Complex::Complex() : real(0), imag(0) {} Complex::Complex(double r, double i) :real(r), imag(i) {} void Complex::display() { cout << "(" << real << ", "; cout << imag << "i)" << endl; } Complex Complex::operator+(Complex &c) { return Complex(real + c.real, imag + c.imag); } ostream &operator<<(ostream &output, const Complex &c) { output<<"("<<c.real<<" + "<<c.imag<<"i)"; return output; }
main:
#include <iostream> #include "Complex.h" using namespace std; int main() { Complex c1(2, 4),c2(6, 10),c3; c3 = c1 + c2; cout << c1 << " + " << c2 << " = " << c3 << endl; return 0; }
输出结果:
(2 + 4i) + (6 + 10i) = (8 + 14i)
提取运算符 >>
Complex 类:
#ifndef PROJECT4_COMPLEX_H #define PROJECT4_COMPLEX_H #include <iostream> using namespace std; class Complex { private: double real; double imag; public: Complex(); Complex(double, double); void display(); Complex operator+(Complex &c); friend ostream& operator<<(ostream &output, const Complex &c); friend istream& operator>>(istream &input, Complex &c); }; #endif //PROJECT4_COMPLEX_H
Complex.cpp:
#include <iostream> #include "Complex.h" using namespace std; Complex::Complex() : real(0), imag(0) {} Complex::Complex(double r, double i) :real(r), imag(i) {} void Complex::display() { cout << "(" << real << ", "; cout << imag << "i)" << endl; } Complex Complex::operator+(Complex &c) { return Complex(real + c.real, imag + c.imag); } ostream &operator<<(ostream &output, const Complex &c) { output<<"("<<c.real<<" + "<<c.imag<<"i)"; return output; } istream &operator>>(istream &input, Complex &c) { cout << "input real part and imaginary part:\n"; input >> c.real >> c.imag; return input; }
main:
#include <iostream> #include "Complex.h" using namespace std; int main() { Complex c1, c2; cin >> c1 >> c2; cout << "c1=" << c1 << endl; cout << "c2=" << c2 << endl; return 0; }
输出结果:
input real part and imaginary part:
2 4
input real part and imaginary part:
6 10
c1=(2 + 4i)
c2=(6 + 10i)
总结
运算符重载使类的设计更加丰富多彩, 扩大了类的功能和使用范围. 运算符重载使得程序易于理解, 易于对对象进行操作. 有了运算符重载, 在声明了类之后, 我们就可以像使用标准类型一样来使用自己声明的类.
类的声明往往是一劳永逸的. 有了好的类, 用户在程序中就不必定义许多成员函数去完成运算和 I/O 的功能, 使主函数更加简单易读. 好的运算符重载能细心啊面向对象程序设计思想.
加载全部内容