关系运算符重载
种类:>,<,==,<=,>=
表达式:左操作数 运算符 右操作数
左操作数:可以是左值,也可以是右值,运算过程中不能被改变。
右操作数:可以是左值,也可以是右值,运算过程中不能被改变。
结果:bool
成员函数实现算数运算符重载
bool operator 运算符(const 类名 &右操作数) const
全局函数实现算数运算符重载
bool operator 运算符(const 类名 &左操作数,const 类名 &右操作数)
#include <iostream>
using namespace std;
//封装类
class Stu
{
friend bool operator>(const Stu &left,const Stu &right);
private:
int a;
int b;
public:
Stu()
{
}
Stu(int a,int b):a(a),b(b)
{
}
void show()
{
cout << "a= " << a << endl;
cout << "b= " << b << endl;
}
/*
//成员函数实现关系运算符重载
bool operator>(const Stu &right) const
{
if(a > right.a && b > right.b)
{
return true;
}
else
{
return false;
}
}
*/
};
//全局函数实现关系运算符重载
bool operator>(const Stu &left,const Stu &right)
{
if(left.a > right.a && left.b > right.b)
{
return true;
}
else
{
return false;
}
}
int main()
{
Stu s1(2,3);
Stu s2(4,5);
if(s1 > s2)
{
cout << "s1>s2" <<endl;
}
else
{
cout << "s1<s2" <<endl;
}
return 0;
}
赋值运算符重载
种类:=,+=,-=,*=,/=
表达式:左操作数 运算符 右操作数
左操作数:只能是左值,运算过程中需要被改变。
右操作数:可以是左值,也可以是右值,运算过程中不能被改变。
结果:自身的引用
成员函数实现算数运算符重载
类名 &operator 运算符(const 类名 &right)
{}
全局函数实现算数运算符重载
类名 &operator 运算符(类名 &light,const 类名 &right)
{}
#include <iostream>
using namespace std;
//封装类
class Stu
{
friend Stu operator+=(Stu &left,const Stu &right);
private:
int a;
int b;
public:
Stu()
{
}
Stu(int a,int b):a(a),b(b)
{
}
void show()
{
cout << "a= " << a << endl;
cout << "b= " << b << endl;
}
/*
//成员函数实现赋值运算符重载
Stu operator+=(const Stu &right)
{
a += right.a;
b += right.b;
return *this;
}
*/
};
//全局函数实现赋值运算符重载
Stu operator+=(Stu &left,const Stu &right)
{
left.a += right.a;
left.b += right.b;
return left;
}
int main()
{
Stu s1(2,3);
Stu s2(4,5);
Stu s3(1,1);
s3 += s2 += s1;
s3.show();
return 0;
}
自增自减运算符重载
种类:++,--
表达式:左操作数 运算符 右操作数
左操作数:只能是左值,运算过程中需要被改变。
右操作数:可以是左值,也可以是右值,运算过程中不能被改变。
结果:自身的引用
成员函数实现前置自增运算符重载
类名 operator ++()
{}
全局函数实现前置自增运算符重载
类名 operator ++(类名 &self)
{}
#include <iostream>
using namespace std;
//封装类
class Stu
{
friend Stu operator++(Stu &self);
private:
int a;
int b;
public:
Stu()
{
}
Stu(int a,int b):a(a),b(b)
{
}
void show()
{
cout << "a= " << a << endl;
cout << "b= " << b << endl;
}
/*
//成员函数实现前置自增运算符重载
Stu operator++()
{
++a;
++b;
return *this;
}
*/
};
//全局函数实现前置自增运算符重载
Stu operator++(Stu &self)
{
++self.a;
++self.b;
return self;
}
int main()
{
Stu s1(2,3);
Stu s2(4,5);
++s1;
s1.show();
return 0;
}
表达式:左操作数 运算符
左操作数:只能是左值,运算过程中需要被改变。
结果:只能是右值(不能改变)
成员函数实现后置自增运算符重载
const 类名 operator ++(int)
{}
全局函数实现后置自增运算符重载
const 类名 operator ++(类名 &self,int)
{}
#include <iostream>
using namespace std;
//封装类
class Stu
{
friend Stu operator++(Stu &self,int);
private:
int a;
int b;
public:
Stu()
{
}
Stu(int a,int b):a(a),b(b)
{
}
void show()
{
cout << "a= " << a << endl;
cout << "b= " << b << endl;
}
/*
//成员函数实现后置自增运算符重载
Stu operator++(int)
{
Stu temp;
temp.a = a++;
temp.b = b++;
return temp;
}
*/
};
//全局函数实现后置自增运算符重载
Stu operator++(Stu &self,int)
{
Stu temp;
temp.a = self.a++;
temp.b = self.b++;
return temp;
}
int main()
{
Stu s1(2,3);
Stu s2(4,5);
Stu s3;
s3 = s1++;
s1.show();
s3.show();
return 0;
}
插入,提取运算符重载
插入符:<<
提取符:>>
表达式:左操作数 运算符 右操作数
左操作数:只能是左值,运算过程中需要被改变。
右操作数:可以是左值,也可以是右值,运算过程中不能被改变。
结果:自身的引用
全局函数实现算数运算符重载
ostream &operator<<(const ostream &cout,const Stu &s)
{}
#include <iostream>
using namespace std;
//封装类
class Stu
{
friend ostream &operator<<(ostream &cout,const Stu &s);
friend istream &operator>>(istream &cin,Stu &s);
private:
int a;
int b;
public:
Stu()
{
}
Stu(int a,int b):a(a),b(b)
{
}
void show()
{
cout << "a= " << a << endl;
cout << "b= " << b << endl;
}
};
//全局函数实现提取,插入运算符重载
ostream &operator<<(ostream &cout,const Stu &s)
{
cout << s.a << s.b <<endl;
return cout;
}
istream &operator>>(istream &cin,Stu &s)
{
cin >> s.a >> s.b;
return cin;
}
int main()
{
Stu s1(2,3);
Stu s2(4,5);
Stu s3;
cin >> s1 >> s2;
cout << s2 << s1 << endl;
return 0;
}
不能重载的运算符
- 访问内部成员
- 指针访问内部成员(->)
- 三目运算符
- 作用域限定符(::)
- sizeof()
静态成员
静态数据成员和静态成员函数属于类,不属于类的某个实例(某个对象),它们在所有实例中都是共享的。
在数据成员前加上static ---> 静态数据成员
在成员函数前加上staric ---> 静态成员函数
静态数据成员必须在类外初始化,如果不初始化,默认为0(不建议)
静态成员函数只能访问静态数据成员,不能访问非静态数据成员
格式:
class 类名
{
static 数据类型 变量名; //静态数据成员
static 返回值类型 函数名(形参列表) //静态成员函数
{}
};
例:
#include <iostream>
using namespace std;
//封装类
class Bank
{
private:
double money;
static double rate; //静态数据成员
public:
Bank()
{
}
Bank(double m):money(m)
{
}
static double getRate() //静态成员函数不能访问非静态数据成员
{
return rate;
}
//静态成员函数(设置当前利率)
static void setRate(double setrate)
{
rate = setrate;
}
//静态成员函数获取本钱+利息
static double show(Bank &all)
{
return all.money*(1+rate);
}
};
double Bank::rate = 0.05;
int main()
{
//获取利率
cout << Bank::getRate() << endl;
//设置利率
Bank::setRate(0.04);
cout << Bank::getRate() << endl;
//获取本钱+利息
Bank b(1000);
cout << Bank::show(b) << endl;
return 0;
}
继承
目的
- 实现带啊吗的复用性(重用性)
- 建立父类和子类之间的联系
- 通过继承,实现多态
概念
在已有类的基础上,增加新的特性,而构造出新类的过程,称为继承或者派生。
格式:
class 类名 :继承方式 类名
{
子类的拓展;
};
//继承方式:public(共有继承) private(私有继承) protected(保护继承)
//一般继承方式为public
继承方式
父类成员访问权限 public | protected | private public | protected | private public | protected | private
继承方式 public protected private
子类通过该继承方式,
父类成员被继承到子类中的访问权限 public | protected | 不可访问 protected | protected | 不可访问 private | private | 不可访问
例:
#include <iostream>
using namespace std;
//封装类
class Person //父类(基类)
{
private:
string name;
protected:
int age;
public:
string sex;
//无参
Person()
{
cout << "无参构造函数" << endl;
}
//有参
Person(string n,int a,string s):name(n),age(a),sex(s)
{
cout << "有参构造函数" << endl;
}
//析构函数
~Person()
{
cout << "析构函数" << endl;
}
void show()
{
cout << "父类:" << name << " " << age << " " << sex << endl;
}
};
//封装学生类,共有继承人类
class Stu:public Person //子类(派生类)
{
private:
double score;
public:
//无参
Stu()
{
cout << "子类无参构造函数" << endl;
}
//有参
Stu(double s,string n,int a,string e):Person(n,a,e),score(s)
{
cout << "子类有参构造函数" << endl;
}
void show()
{
cout << sex << endl; //子类可以访问从父类继承下来的共有成员
cout << age << endl; //子类可以访问从父类继承下来的受保护成员
//cout << name << endl; //子类不可以访问从父类继承下来的私有成员
}
};
int main()
{
Stu s(65,"zhang",18,"男");
s.Person::show();
return 0;
}
注意:
- 父类的构造需要赶在子类构造之前,在书写子类的初始化列表时,需要注意先后顺序
- 当父类和子类有同名无参函数时,它们既不是重复定义,也不是重载。(作用域不同)
多继承
概念
一个类由多个类共同派生。
格式:
class 类名:继承方式1 类名1,继承方式2 类名2,......继承方式n 类名n
{
子类的拓展;
};
练习
搭建一个货币的场景,创建一个名为 RMB 的类,该类具有整型私有成员变量 yuan(元)、jiao(角)和 fen(分),并且具有以下功能:
(1)重载算术运算符 + 和 -,使得可以对两个 RMB 对象进行加法和减法运算,并返回一个新的 RMB 对象作为结果。
(2)重载关系运算符 >,判断一个 RMB 对象是否大于另一个 RMB 对象,并返回 true 或 false。
(3)重载前置减减运算符 --,使得每次调用时 RMB 对象的 yuan、jiao 和 fen 分别减 1
(4)重载后置减减运算符 --,使得每次调用时 RMB 对象的 yuan、jiao 和 fen 分别减 1
(5)另外, RMB 类还包含一个静态整型成员变量 count,用于记录当前已创建的 RMB 对象的数量。每当创建一个新的 RMB 对象时,count 应该自增 1;每当销毁一个 RMB 对象时,count 应该自减 1。
要求,需要在main 函数中测试上述RMB 类的功能。
#include <iostream>
using namespace std;
//封装类
class RMB
{
private:
int yuan;
int jiao;
int fen;
int count;
public:
//无参
RMB()
{
count++;
}
//有参
RMB(int y,int j,int f):yuan(y),jiao(j),fen(f)
{
count++;
}
//成员函数实现+运算符重载
const RMB operator+(const RMB &right) const
{
RMB temp;
temp.yuan = yuan + right.yuan;
temp.jiao = jiao + right.jiao;
temp.fen = fen + right.fen;
return temp;
}
//成员函数实现-运算符重载
const RMB operator-(const RMB &right) const
{
RMB temp;
temp.yuan = yuan - right.yuan;
temp.jiao = jiao - right.jiao;
temp.fen = fen - right.fen;
return temp;
}
//成员函数实现>运算符重载
bool operator>(const RMB &right) const
{
if(yuan > right.yuan && jiao > right.jiao && fen > right.fen)
{
return true;
}
else
{
return false;
}
}
//成员函数实现前置自增运算符重载
RMB operator--()
{
--yuan;
--jiao;
--fen;
return *this;
}
//成员函数实现后置自增运算符重载
RMB operator--(int)
{
RMB temp;
temp.yuan = yuan--;
temp.jiao = jiao--;
temp.fen = fen--;
return temp;
}
//析构函数
~RMB()
{
count--;
}
void show()
{
cout << yuan << " " << jiao << " " << fen << endl;
}
};
int main()
{
RMB r1(10,9,6);
RMB r2(20,8,4);
RMB r3 = r1 + r2;
RMB r4 = r1 - r2;
r1.show();
r2.show();
r3.show();
r4.show();
r1--;
r1.show();
--r1;
r1.show();
return 0;
}