C++第四章学习

类与对象

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)的映射关系。

©️2020 CSDN 皮肤主题: 1024 设计师:上身试试 返回首页