2021-3-22 第九天
C++内容学习
w3school -> C++ -> 面向对象
网址:https://www.w3cschool.cn/cpp/cpp-data-structures.html
三)C++重载运算符和重载函数
允许在同一作用域中的某个函数和运算符指定多个定义
#但是它们的参数列表和定义(实现)不相同
当调用重载函数/运算符时,编译器会进行比较,选择最合适的定义。
C++中函数重载
可声明几个功能类似的同名函数,但这些同名函数的形参必须不同(参数的个数、类型或顺序)
例:
void print(int i){
cout<<"Printing int : "<<i<<endl;
}
void print(double f){
cout<<"Printing float : "<<f<<endl;
}
void print(char* c){
cout<<"Printing character : "<<c<<endl;
}
C++中运算符重载
大部分C++内置的运算符1都可以重定义或重载
重载运算符是带有特殊名称的函数,由operator+要重载的运算符组成
例:
Box operator+(const Box&);
//声明加法运算符,用于Box对象间的相加
不可重载的运算符列表:
①:: ②.* ③. ④?:
运算符重载的分类:
- 一元运算符重载
- 二元运算符重载
- 关系运算符重载
- 输入/输出运算符重载
- ++和—运算符重载
- 赋值运算符重载
- 函数调用运算符()重载
- 下标运算符[]重载
- 类成员访问运算符->重载
1、一元运算符重载
只对一个操作数进行操作
如: ++、–、负号(-)、逻辑非(!)
例:
#include <iostream>
using namespace std;
class Distance{
public:
Distance(){
feet = 0;
inches = 0;
}
Distance(int f, int i):feet(f), inches(i){}
Distance(const Distance &c){
feet = c.feet;
inches = c.inches;
}
Distance operator-(){
Distance d;
d.feet = -feet;
d.inches = inches;
return d;
}
Distance operator-(const Distance& d){
Distance dis;
dis.feet = feet - d.feet;
dis.inches = inches - d.inches;
cout<<"my feet:"<<feet<<endl;
cout<<"its feet:"<<d.feet<<endl;
return dis;
}
~Distance(){}
int C(){
return feet*inches;
}
void show(){
cout<<"feet:"<<this->feet<<"; inches:"<<this->inches<<endl;
}
private:
int feet;
int inches;
};
int main()
{
Distance d;
Distance d1(3,4);
Distance d2(d);
Distance d3;
d = -d1;
d3 = d1 - d;
cout<<"d3:"<<endl;
d3.show();
cout<<"d1.C():"<<d1.C()<<endl;
cout<<"d2.C():"<<d2.C()<<endl;
cout<<"d.C():"<<d.C()<<endl;
return 0;
}
2、二元运算符重载
二元运算符需要两个参数,+、-、*、/ 等运算都属于二元运算符
Distance operator+(const Distance& d){
Distance distance;
Distance.feet = this->feet + d.feet;
Distace.inches = this->inches + d.inches;
return distance;
//this可省略
}
Distance d3 = d1 + d2;
#对d3的初始化过程,调用了对象d1中的重载加法运算
#因此+号前的第一个参数代入的是d1对象
#而重载加法运算中,括号里引用的参数,此时由+号后的d2对象代入
例:
#include <iostream>
using namespace std;
class Complex{
private:
double m_real;
double m_imag;
public:
void show();
friend istream &operator>>(istream &in, Complex &A){
in >> A.m_real >> A.m_imag;
return in;
}
friend ostream &operator<<(ostream &out, const Complex &A){
out << A.m_real << "+" << A.m_imag << "i" ;
return out;
}
};
void Complex::show(){
cout<<this->m_real<<"+"<<this->m_imag<<"i"<<endl;
}
int main()
{
Complex c1, c2;
cout<<"Please input the real and imag:";
cin>>c1>>c2;
cout<<"The output of the real and imag:";
cout<<c1<<endl;
cout<<c2<<endl;
return 0;
}
#关系运算符
#< >号,一般返回true或false
#不再赘述
3、输入/输出运算符重载
可以重载流提取运算符>>,和流插入运算符<<,来操作用户自定义的数据类型
#如果把运算符重载声明为类的友元函数,就能不用创建对象而直接调用函数
用友元函数来表示
1)重载输入运算符>>
friend istream &operator>>(istream &in, complex &A){
in>>A.m_real>>A.m_imag;
return in;
}
2)重载输出运算符<<
friend ostream &operator<<(ostream &out, complex &A){
out<<A.m_real<<A.m_imag;
}
例:
#include <iostream>
using namespace std;
class Complex{
private:
double m_real;
double m_imag;
public:
void show();
friend istream &operator>>(istream &in, Complex &A){
in >> A.m_real >> A.m_imag;
return in;
}
friend ostream &operator<<(ostream &out, const Complex &A){
out << A.m_real << "+" << A.m_imag << "i" ;
return out;
}
};
void Complex::show(){
cout<<this->m_real<<"+"<<this->m_imag<<"i"<<endl;
}
int main()
{
Complex c1, c2;
cout<<"Please input the real and imag:";
cin>>c1>>c2;
cout<<"The output of the real and imag:";
cout<<c1<<endl;
cout<<c2<<endl;
return 0;
}
4、()运算符重载
用于增强操作C++数组的功能
例:
#include <iostream>
#define SIZE 10
using namespace std;
class Safearray{
private:
int arr[SIZE];
public:
Safearray(){
int i;
for(i = 0;i < SIZE;i++){
this->arr[i] = i;
}
}
int &operator[](int i){
if(i > SIZE){
cout<<"索引超过最大值"<<endl;
return arr[0];
}
return arr[i];
}
};
int main()
{
Safearray A;
cout<<"A[2]的值为:"<<A[2]<<endl;
cout<<"A[5]的值为:"<<A[5]<<endl;
cout<<"A[12]的值为:"<<A[12]<<endl;
return 0;
}
5、->类成员访问运算符重载
#暂时看不太懂
https://www.w3cschool.cn/cpp/class-member-access-operator-overloading.html
四)C++多态
例:
//基类中有一个函数area(),派生类也有一个函数area()
Shape *shape;
Rectangle rec(10,7);
Triangle tri(10,5);
shape = &rec;
shape->area();
shape = &tri;
shape->area();
则,此时调用的area()函数为基类的area()函数
因为此时编译器看的是指针的类型。
这就是静态多态,或静态链接。
但,如果在基类Shape中,函数area()的声明前加上关键词virtual
则此时调用两个派生类的area()函数。
例:
#include <iostream>
using namespace std;
class Shape{
protected:
int width;
int depth;
public:
Shape(int w, int d){
width = w;
depth = d;
}
virtual int area(){
cout<< "Parent class area:" <<endl;
return 0;
}
};
class Rectangle:public Shape{
public:
Rectangle(int w = 0, int d =0):Shape(w,d){}
int area(){
cout<< "Rectangle class area:" <<endl;
return (width*depth);
}
};
class Triangle:public Shape{
public:
Triangle(int w = 0, int d =0):Shape(w,d){}
int area(){
cout<< "Triangle class area:" <<endl;
return (width*depth/2);
}
};
int main()
{
Shape *shape;
Rectangle rec(10,7);
Triangle tri(10,5);
rec.area();
tri.area();
shape = &rec;
shape->area();
shape = &tri;
shape->area();
return 0;
}
#此时,编译器看的是指针的内容,而不是它的类型
由于tri和rec类的对象的地址存储在*shape中,所以会调用派生类的area()函数
这种:每个子类都有一个函数area()的独立实现,这就是多态的一般使用方式。
有了多态,可以有多个不同的类,都带有同一名称但不同实现的函数。
虚函数:在基类中使用关键字virtual声明的函数
在派生类中重新定义基类中定义的虚函数时,会告诉编译器不要静态链接到该函数。
这种操作被称为动态链接或后期绑定。
纯虚函数:不想对基类中的虚函数给出有意义实现
例:
class Shape{
…
virtual int area() = 0;
};
“=0”告诉编译器,函数没有主题,上面的虚函数是纯虚函数。