第12课 - 操作符重载 - 上
一.使用C++标准库
1.1 C++标准库并不是C++语言的一部分
1.2 C++标准库是由C++语言编写而成的类库和函数的集合
1.3 C++标准库中定义的类和对象都位于std命名空间中
1.4 C++标准库的头文件都不带.h后缀
1.5 C++标准库涵盖了C库的功能
C库中<name.h>头文件对应C++中的<cname>
1.6 C库中++标准库与定义了多种常用的数据结构,如:字符串,链表,队列,栈等
Source Example 1: #include <cstdio> using namespace std; int main() { /* C++标准库中的printf函数 */ printf ("hello world!\n"); return 0; }
1.7 C++标准库中的输入输出类
cout对象(显示器对象,输出)
cin对象(键盘对象,输入)
Source Example 1.7: #include <iostream> using namespace std; int main() { cout << "Hello World"<< endl; int x,y; cout << "1th parameter: "; cin >> x; cout << "2th parameter: "; cin >> y; cout << "Result: "<<x+y<<endl; return 0; }
1.8 在C语言中<<,>>只能用于整数运算,但是C++改变了左移和右移运算符的语义。
二. 操作符重载
2.1 操作符重载为操作符提供不同的语义
Source Example 2.1: #include <iostream> using namespace std; struct Comples { int a; int b; }; int main() { Comples c1 = {1,2}; Comples c2 = {1,3}; /* 编译器报错,加法不可以用于两个结构体 */ Comples c3 = c1 + c2; return 0; }
解决方法:
定义一个add函数用于两个Complex的相加,修改代码如下
#include <iostream> using namespace std; struct Complex { int a; int b; }; /* 使用引用更为高效,否则还要拷贝构造 */ Complex add(const Complex& c1, const Complex& c2 ) { Complex ret; ret.a = c1.a + c2.a; ret.b = c1.b + c2.b; return ret; } int main() { Complex c1 = {1,2}; Complex c2 = {1,3}; Complex c3 = add(c1, c2); cout<<"c3.a = "<<c3.a<<endl; cout<<"c3.b = "<<c3.b<<endl; return 0; }
2.2 C++提供了操作符重载
2.2.1 C++中操作符重载的本质
a.C++中通过operate关键字可以利用函数扩展操作符
b.operate的本质也是通过函数重载实现操作符重载
代码修改如下:#include <iostream> using namespace std; struct Complex { int a; int b; }; /* 使用引用更为高效,否则还要拷贝构造 */ Complex operator+ (const Complex& c1, const Complex& c2 ) { Complex ret; ret.a = c1.a + c2.a; ret.b = c1.b + c2.b; return ret; } int main() { Complex c1 = {1,2}; Complex c2 = {1,3}; /* 等价于 Complex c3 = operator+(c1, c2);*/ /* 本质就是函数调用 */ Complex c3 = c1 + c2; cout<<"c3.a = "<<c3.a<<endl; cout<<"c3.b = "<<c3.b<<endl; return 0; }
2.3 用operator关键字扩展的操作符可以用于类吗?
2.3.1 a,b属于类的私有数据,无法直接进行访问
Complex operator+ (const Complex& c1, const Complex& c2 ) { Complex ret; ret.a = c1.a + c2.a; ret.b = c1.b + c2.b; return ret; }
2.3.2 C++中的友元
private声明使得类的成员不能被外界访问,但是通过friend关键字可以例外的开放权限
Source Example 2.3.2 #include <iostream> using namespace std; class Complex { int a; int b; public: Complex(int a = 0, int b = 0) { this->a = a; this->b = b; } int GetA() { return a; } int GetB() { return b; } friend Complex operator+ (const Complex& c1, const Complex& c2 ); }; Complex operator+ (const Complex& c1, const Complex& c2 ) { Complex ret; ret.a = c1.a + c2.a; ret.b = c1.b + c2.b; return ret; } int main() { Complex c1(1,2); Complex c2(1,3); Complex c3 = c1 + c2; /* 输出结果为c3.a = 2 */ /* 输出结果为c3.b = 5 */ cout<<"c3.a = "<<c3.GetA()<<endl; cout<<"c3.b = "<<c3.GetB()<<endl; return 0; }
2.4 重载左移运算符
为了实现输出
cout<<c1<<endl;
cout<<c2<<endl;
cout<<c3<<endl;
我们要自己实现左移操作符,让左移操作符识别Complex;
Source Example 2.4: #include <iostream> using namespace std; class Complex { int a; int b; public: Complex(int a = 0, int b = 0) { this->a = a; this->b = b; } int GetA() { return a; } int GetB() { return b; } /* 开放对下面两个函数的权限 */ friend ostream& operator<< (ostream& out, const Complex& c); friend Complex operator+ (const Complex& c1, const Complex& c2 ); }; ostream& operator<< (ostream& out, const Complex& c) { out<<c.a<<" + "<<c.b<<"i"; /* 必须返回out,如果不返回无法进行链式输出(cout<<c1<<endl) * cout<<c1 <==> operator<<(cout, c1); * 显然如果不返回无法进行链式输出 * (cout<<c1<<endl) <==> operator<<(perator(cout, c1), endl) */ return out; } Complex operator+ (const Complex& c1, const Complex& c2 ) { Complex ret; ret.a = c1.a + c2.a; ret.b = c1.b + c2.b; return ret; } int main() { Complex c1(1,2); Complex c2(1,3); Complex c3 = c1 + c2; cout<<c1<<endl; cout<<c2<<endl; cout<<c3<<endl; return 0; }
输出结果如下: