类与对象
面向对象的编程方式使得每一个类都只做一件事。面向过程会让一个类越来越全能,就像一个管家一样做了所有的事。
例如:
面向对象:商店中秋打折、国庆打折、情人节打折,都继承 打折 这个类,然后创建三个类,无需修改原来的类,删除也只需要直接把不需要的打折类型所属的类删除即可。
面向过程:这三种打折方式都只能在 打折 这个类中进行修改,需要增补很多的if判断,把原来的 打折 类弄得很复杂,易出错。
1.类用于指定对象的形式,它包含了数据表示法和用于处理数据的方法。
⭐️对象:现实中对象的模拟,具有属性和行为。
⭐️类:同一类对象的共同属性和行为。
🉑:定义对象时,通过构造函数初始化。
🉑:删除对象时,通过析构函数释放资源。
多动手编程
2.类定义是以关键字 class 开头,后跟类的名称。类的主体是包含在一对花括号中。类定义后必须跟着一个分号或一个声明列表。
class Box
{
public:
double length; // 盒子的长度
double breadth; // 盒子的宽度
double height; // 盒子的高度
};
3.每个类包含数据说明和一组操作数据或传递消息的函数。类的实例称为对象.
类提供了对象的蓝图,所以基本上,对象是根据类来创建的。声明类的对象,就像声明基本类型的变量一样。下面的语句声明了类 Box 的两个对象:
Box Box1; // 声明 Box1,类型为 Box
Box Box2; // 声明 Box2,类型为 Box
访问数据成员实例:
#include <iostream>
using namespace std;
class Box
{
public:
double length; // 长度
double breadth; // 宽度
double height; // 高度
};
int main( )
{
Box Box1; // 声明 Box1,类型为 Box
Box Box2; // 声明 Box2,类型为 Box
double volume = 0.0; // 用于存储体积
// box 1 详述
Box1.height = 5.0;
Box1.length = 6.0;
Box1.breadth = 7.0;
// box 2 详述
Box2.height = 10.0;
Box2.length = 12.0;
Box2.breadth = 13.0;
// box 1 的体积
volume = Box1.height * Box1.length * Box1.breadth;
cout << "Box1 的体积:" << volume <<endl;
// box 2 的体积
volume = Box2.height * Box2.length * Box2.breadth;
cout << "Box2 的体积:" << volume <<endl;
return 0;
}
私有的或者受保护的成员不能用直接成员访问运行符(.)来直接访问,但public类可以这样访问。
4.[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-YGzKW7zw-1600595762995)(C:\Users\lenovo\AppData\Roaming\Typora\typora-user-images\1600269596177.png)]
(1) 声明类型之后声明变量employee worker1,worker2,*Emp;
(2) 声明类型的同时声明变量worker1,worker2, *Emp;
(3) 直接声明结构类型变量没有了标识符的存在,其他与(2)相同
面向对象程序的基本特点
- 抽象
对同一类的对象的共同属性和行为进行概括,形成类。
抽象的实现:类
数据抽象:
*int hour,int minute,int second
代码抽象:
*setTime(),showTime()
*封装:将抽象出来的数据、代码封装在一起,形成类。
程序中使用{}实现封装的效果
*继承:在已有类的基础上,进行扩展形成新的类。
*多态:同一名称,不同的功能实现方式。
目的-达到行为标识统一,减少程序中标识符的个数。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-z5pc4UyK-1600595763003)(C:\Users\lenovo\AppData\Roaming\Typora\typora-user-images\1600340581496.png)]
类和对象的定义
类:类型。
class 类名称
{
public:
共有成员(外部接口)
private:
私有成员
protected:
保护型成员
};
类内初始值举例:
class Clock{
public:
void setTime(int newH,int newM,int newS);
void showTime();
private:
int hour = 0,minute = 0,second = 0;//类内的初始值
}
私有成员:只允许本类中的函数来进行访问,除了私元。
保护型成员:与私有成员类似,差别表现在继承和派生。
类是一类对象的设计,对象使类的实例。
对象定义的语法:
类名 对象名;
例如:Clock myClock;
类外访问成员使用“对象名.成员名”方式访问public成员
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-UiI8Uqr1-1600595763007)(C:\Users\lenovo\AppData\Roaming\Typora\typora-user-images\1600345255281.png)]
类和对象的程序举例
#include <iostream>
using namespace std;
class Clock{
public:
void setTime(int newH = 0,int newM = 0,int newS = 0);
void showTime();
private:
int hour,minute,second;
};
//成员函数的实现
//类名:: --- important
void Clock::setTime(int newH,int newM,int newS){
hour = newH;
minute = newM;
second = newS;
}
void Clock::showTime(){
cout<<hour<<":"<<minute<<":"<<second;
}
int main( )
{
Clock myClock;
myClock.setTime(8,30,30);
myClock.showTime();
return 0;
}
//----- class类后面要跟上; -----//
构造函数基本概念
💠类中的特殊函数
💠用于描述初始化算法
💠在对象被创建时使用特定的值构造对象,将对象初始化为一个特定的初始状态。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-UtCVDqZS-1600595763012)(C:\Users\lenovo\AppData\Roaming\Typora\typora-user-images\1600350916389.png)]
构造函数的调用时机
- 在对象创建时被自动调用
例如:Clock myClock(0,0,0)
在类中同时出现以下的两个构造函数,将发生编译出错
1. Clock(); 2. Clock(int newH = 0,int newM = 0);
构造一个新对象必须调用构造函数
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-hRGKKT8L-1600595763015)(C:\Users\lenovo\AppData\Roaming\Typora\typora-user-images\1600351741884.png)]
//构造函数例题(1)
#include <iostream>
using namespace std;
class Clock{
public:
Clock(int newH,int newM,int newS);//构造函数
void setTime(int newH = 0,int newM = 0,int newS = 0);
void showTime();
private:
int hour,minute,second;
};
//-------------构造函数的实现-------------//
Clock::Clock(int newH,int newM,int newS):hour(newH),minute(newM),second(newS){}
//初始化: newH赋值给hour newM赋值给minute newS赋值给second
//-------------------------------------//
//成员函数的实现
//类名:: --- important
void Clock::setTime(int newH,int newM,int newS){
hour = newH;
minute = newM;
second = newS;
}
void Clock::showTime(){
cout<<hour<<":"<<minute<<":"<<second;
}
int main( )
{
Clock c(8,30,30); //自动调用构造函数
c.showTime();
return 0;
}
//构造函数例题(2)
#include <iostream>
using namespace std;
class Clock{
public:
Clock(int newH,int newM,int newS);//构造函数
Clock();//默认构造函数,可以提供一个通用的类,提高重载率,无默认可能会报错
void setTime(int newH = 0,int newM = 0,int newS = 0);
void showTime();
private:
int hour,minute,second;
};
//-------------构造函数的实现-------------//
Clock::Clock(int newH,int newM,int newS):hour(newH),minute(newM),second(newS){}
Clock::Clock():hour(0),minute(0),second(0){}//初始化
//-------------------------------------//
//成员函数的实现
//类名:: --- important
void Clock::setTime(int newH,int newM,int newS){
hour = newH;
minute = newM;
second = newS;
}
void Clock::showTime(){
cout<<hour<<":"<<minute<<":"<<second;
}
int main()
{
Clock c(8,30,30); //调用有参数的构造函数
Clock c2; //调用无参数的构造函数,即默认构造函数
c.showTime();
c2.showTime();
return 0;
}
//委托构造函数,不必重复写构造函数
Clock::Clock(int newH,int newM,int newS):hour(newH),minute(newM),second(newS){}
Clock::Clock():Clock(0,0,0){}
//复制构造函数
默认的复制构造函数会实现两个对象之间的数据一一对应,对应复制。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qIMhg4A2-1600595763017)(C:\Users\lenovo\AppData\Roaming\Typora\typora-user-images\1600499222428.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-KKRPLfs8-1600595763021)(C:\Users\lenovo\AppData\Roaming\Typora\typora-user-images\1600499359692.png)]
“= delete”指示编译器不生成复制构造函数
//复制构造函数调用举例
//成员函数的实现
Point::Point(const Point &p){
x = p.x;
y = p.y;
cout<<"正在调用复制构造"<<endl;
}
//形参为Point类对象的函数
void fun1(Point p){
cout<<p.getX()<<endl;
}
//返回值为Point类对象的函数
Point fun2(){ //会发生复制构造,传给调用者
Point a;
return a;
}
int main(){
Point a;//构造A
Point b(a);//用A复制构造B,第一次复制构造函数调用
cout<<b.getX()<<endl;
fun1(b);//用对象作为实参,第二次复制构造函数调用
b = fun2(); //返回值是类对象,第三次复制构造函数调用
cout<<b.getX()<<endl;
return 0;
}
//析构函数,完成对象被删除前的一些清理的工作,例如关闭一些文件,析构函数会在对象消亡时被自动调用,释放资源
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-UptBhxQy-1600595763023)(C:\Users\lenovo\AppData\Roaming\Typora\typora-user-images\1600500652030.png)]
//例子
#include <iostream>
using namespace std;
class Point{
//...其他函数原型
private:
int x,y;
public:
Point(int xx,int yy);
~Point();
};
Point::Point(int xx,int yy)
{
x= xx;
y = yy;
}
Point::~Point(){} //~Point是析构函数的函数名
//...其他函数的实现略
类的组合
类中的成员是另一个类的对象。可以在已有抽象的基础上实现更复杂的抽象。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5z010Gd4-1600595763025)(C:\Users\lenovo\AppData\Roaming\Typora\typora-user-images\1600503525149.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-7ivZ6yqV-1600595763027)(C:\Users\lenovo\AppData\Roaming\Typora\typora-user-images\1600503650283.png)]
//类的组合例子
#include <iostream>
#include <cmath>
#define endl '\n'
using namespace std;
class Point { //Point类定义
public:
Point(int xx = 0, int yy = 0) {
x = xx;
y = yy;
}
Point(Point &p);
int getX() { return x; }
int getY() { return y; }
private:
int x, y;
};
Point::Point(Point &p) { //复制构造函数的实现
x = p.x;
y = p.y;
cout << "Calling the copy constructor of Point" << endl;
}
//类的组合
class Line { //Line类的定义
public: //外部接口
Line(Point xp1, Point xp2);
Line(Line &l);
double getLen() { return len; }
private: //私有数据成员
Point p1, p2; //Point类的对象p1,p2
double len;
};
//组合类的构造函数
Line::Line(Point xp1, Point xp2) : p1(xp1), p2(xp2) {
cout << "Calling constructor of Line" << endl;
double x = static_cast<double>(p1.getX() - p2.getX());
double y = static_cast<double>(p1.getY() - p2.getY());
len = sqrt(x * x + y * y);
}
Line::Line (Line &l): p1(l.p1), p2(l.p2) {//组合类的复制构造函数
cout << "Calling the copy constructor of Line" << endl;
len = l.len;
}
//主函数
int main() {
Point myp1(1, 1), myp2(4, 5); //建立Point类的对象
Line line(myp1, myp2); //建立Line类的对象
Line line2(line); //利用复制构造函数建立一个新对象
cout << "The length of the line is: ";
cout << line.getLen() << endl;
cout << "The length of the line2 is: ";
cout << line2.getLen() << endl;
return 0;
}
前向引用说明
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-NCo29Q37-1600595763029)(C:\Users\lenovo\AppData\Roaming\Typora\typora-user-images\1600506790694.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-TePi3eUn-1600595763031)(C:\Users\lenovo\AppData\Roaming\Typora\typora-user-images\1600506868126.png)]
数据成员的构造顺序只与其在类中声明顺序有关。
UML简介
可视化建模语言,1.事物 2.关系 3.图
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-T1jbbWNg-1600595763033)(C:\Users\lenovo\AppData\Roaming\Typora\typora-user-images\1600507283022.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-gRbKQNKR-1600595763034)(C:\Users\lenovo\AppData\Roaming\Typora\typora-user-images\1600507323750.png)]
//结构体和联合体,C++结构体是一种特殊形态的类。与类的唯一区别:结构体的缺省访问权限是public,而类的缺省访问权限是private。
选择结构体,why:定义主要用来保存数据,而没有什么操作的类型。成员可以是数据成员,函数成员。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Fg548DEF-1600595763036)(C:\Users\lenovo\AppData\Roaming\Typora\typora-user-images\1600515082011.png)]
什么控制属性类型不写就默认结构体的变量为public属性。
联合体是为了存储空间的共用,所有的成员共用同一组内存单元,任何两个成员不会同时有效。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qBoZSXb9-1600595763037)(C:\Users\lenovo\AppData\Roaming\Typora\typora-user-images\1600515411302.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-vJXakEH5-1600595763039)(C:\Users\lenovo\AppData\Roaming\Typora\typora-user-images\1600515785587.png)]
共用字节空间大小按照最多字节数的那个成员来分配,上例是四个字节大小。
#include <string>
#include <iostream>
using namespace std;
class ExamInfo{
private:
string name;
enum{GRADE,PASS,PERCENTAGE}mode;
union{
char grade;
bool pass;
int percent;
};
public:
ExamInfo(string name,char grade)
:name(name),mode(GRADE),grade(grade){}
ExamInfo(string name,bool pass)
:name(name),mode(PASS),pass(pass){}
ExamInfo(string name,int percent)
:name(name),mode(PERCENTAGE),percent(percent){}
void show();
};
void ExamInfo::show(){
cout<<name<<":";
switch(mode){
case GRADE:cout<<grade;break;
case PASS:cout<<(pass?"PASS":"FAIL");break;
case PERCENTAGE:cout<<percent;break;
}
cout<<endl;
}
int main() {
ExamInfo course1("English", 'B');
ExamInfo course2("Calculus", true);
ExamInfo course3("C++ Programming", 85);
course1.show();
course2.show();
course3.show();
return 0;
}
//总结:类结束时的{}后要加上;
枚举类
语法类型:enum class 枚举类型名:底层类型{枚举值列表};
例:enum class Type:char{ General,Light,Medium,Heavy};
例:使用Type的枚举值General Type::General
优势:强作用域,其作用域限制在枚举类中。
无法直接比较不同的枚举类
实验四(上)
return 执行之前会进行析构函数的执行
实验四(下)
//#include "stdafx.h"
#include <iostream>
using namespace std;
enum CPU_Rank{P1=1,P2,P3,P4,P5,P6,P7};
class CPU{
private:
CPU_Rank rank;
int frequency;
float voltage;
public:
CPU(CPU_Rank r,int f,float v)
{
rank = r;
frequency = f;
voltage = v;
cout<<"构造了一个CPU"<<endl;
}
CPU(CPU & c)
{
rank = c.rank;
frequency = c.frequency;
voltage = c.voltage;
cout<<"拷贝构造了一个CPU"<<endl;
}
~CPU(){cout<<"析构了一个CPU"<<endl;}//析构函数
CPU_Rank GetRank() const {return rank;}
int GetFrequency() const {return frequency;}
float GetVoltage() const {return voltage;}
void SetRank(CPU_Rank r){rank = r;}
void SetFrequency(int f){frequency = f;}
void SetVoltage(float v){voltage = v;}
void Run(){cout<<"CPU开始运行"<<endl;}
void Stop(){cout<<"CPU停止运行"<<endl;}
};
enum RAM_Type{DDR2 = 2,DDR3,DDR4};
class RAM
{
private:
enum RAM_Type type;
unsigned int frequency;//MHZ
unsigned int size;//GB
public:
//构造函数
RAM(RAM_Type t,unsigned int f,unsigned int s){
type = t;
frequency = f;
size = s;
cout<<"构造了一个RAM"<<endl;
}
~RAM(){cout<<"析构了一个RAM"<<endl;}
//用于设置三个私有数据成员
RAM_Type GetType() const{return type;}
unsigned int GetFrequency() const {return frequency;}
unsigned int GetSize() const{return size;}
//用于获取三个私有成员数据的值
void SetType(RAM_Type t){type = t;}
void SetFrequency(unsigned int f){frequency = f;}
void SetSize(unsigned int s){size = s;}
void Run(){cout<<"RAM开始运行"<<endl;}
void Stop(){cout<<"RAM停止运行"<<endl;}
};
enum CDROM_Interface{SATA,USB};//接口类
enum CDROM_Install_type{external,built_in};//安装类型
class CD_ROM
{
private:
enum CDROM_Interface inter_type;
unsigned int cache_size;//MB
CDROM_Install_type install_type;
public:
CD_ROM(CDROM_Interface i,unsigned int s,CDROM_Install_type it)
{
inter_type =i;
cache_size =s;
install_type = it;
cout<<"构造了一个D_ROM"<<endl;
}
~CD_ROM(){cout<<"析构了一个CD_ROM"<<endl;}
CDROM_Interface GetInterfaceType() const {return inter_type;}
unsigned int GetSize() const {return cache_size;}
CDROM_Install_type GetInstallType() const {return install_type;}
void SetInterfaceType(CDROM_Interface i){inter_type = i;}
void SetSize(unsigned int s){cache_size = s;}
void SetInstallType(CDROM_Install_type it){install_type = it;}
void Run(){cout<<"CD_RAM开始运行"<<endl;}
void Stop(){cout<<"CD_RAM停止运行"<<endl;}
};
class COMPUTER
{
private:
//三个前面定义的私有数据成员
CPU my_cpu;
RAM my_ram;
CD_ROM my_cdrom;
//两个简单类型的私有数据成员
unsigned int storage_size;
unsigned int bandwidth;
public:
COMPUTER(CPU c,RAM t,CD_ROM cd,unsigned int s,unsigned int b);
~COMPUTER(){cout<<"析构了一个COMPUTER"<<endl;}
void Run()
{
my_cpu.Run();
my_ram.Run();
my_cdrom.Run();
cout<<"COMPUTER开始运行"<<endl;
}
void Stop()
{
my_cpu.Stop();
my_ram.Stop();
my_cdrom.Stop();
cout<<"COMPUTER停止运行"<<endl;
}
};
COMPUTER::COMPUTER(CPU c,RAM r,CD_ROM cd,unsigned int s,unsigned int b):my_cpu(c),my_ram(r),my_cdrom(cd)
{
storage_size = s;
bandwidth = b;
cout<<"构造了一个COMPUTER"<<endl;
}
int main()
{
CPU a(P6,300,2.8);
a.Run();
a.Stop();
cout<<"********************************\n";
RAM b(DDR3,1600,8);
b.Run();
b.Stop();
cout<<"*******************************\n";
CD_ROM c(SATA,2,built_in);
c.Run();
c.Stop();
cout<<"**********************************\n";
COMPUTER my_computer(a,b,c,128,10);
cout<<"***********************************\n";
my_computer.Run();
my_computer.Stop();
cout<<"**************************************\n";
return 0;
}
//结果
构造了一个CPU
CPU开始运行
CPU停止运行
********************************
构造了一个RAM
RAM开始运行
RAM停止运行
*******************************
构造了一个D_ROM
CD_RAM开始运行
CD_RAM停止运行
**********************************
拷贝构造了一个ROM
拷贝构造了一个RAM
拷贝构造了一个CPU
拷贝构造了一个CPU
拷贝构造了一个RAM
拷贝构造了一个ROM
构造了一个COMPUTER
析构了一个CPU
析构了一个RAM
析构了一个CD_ROM
***********************************
CPU开始运行
RAM开始运行
CD_RAM开始运行
COMPUTER开始运行
CPU停止运行
RAM停止运行
CD_RAM停止运行
COMPUTER停止运行
**************************************
析构了一个COMPUTER
析构了一个CD_ROM
析构了一个RAM
析构了一个CPU
析构了一个CD_ROM
析构了一个RAM
析构了一个CPU
第四章小结
1.学习了声明类、定义类的对象
2.定义构造函数,对对象进行初始化
3.当对象消亡的时候,我们要调用析构函数,去释放一些资源
4.在类里面定义内联函数,将一些简单的函数定义为内联的形式,可以提高程序的运行效率
5.自定义复制构造函数可以使用一个已有的对象去初始化一个新对象
6.类的组合、结构体、联合体、枚举类。
7.关于构造和析构函数调用顺序的解释:最先被调用的构造函数,其对应(同一对象中的)析构函数最后被调用,而最后被调用的构造函数,其对应的析构函数最先被调用
杂—关于redis
分布式:多台机器(nodes)同时存储数据和状态,彼此交换消息来保持数据一致,可视为一个完整的存储系统。
作为Key-value型数据库,Redis也提供了键(Key)和键值(Value)的映射关系。