目录

  • 一、类型与对象的概念
    • 1.1什么是对象
    • 1.2类型
  • 二、如何在计算机中描述类型
    • 2.1使用结构体(struct)对类型进行描述
    • 2.2使用类(class)对类型进行描述
  • 三、构造函数
    • 3.1构造函数概述
    • 3.2一个知识点
  • 四、一个对象创建的过程
  • 五、构造函数的应用
    • 5.1 要点
    • 5.2 初始化列表
  • 六、头文件和实现文件的分离
  • 七、this指针
    • 7.1 this指针概述
    • 7.2 this的使用
  • 八、析构函数
    • 8.1概述
    • 8.2析构函数程序举例:

一、类型与对象的概念

1.1什么是对象

 万物皆对象程序就是由一组对象组成的,对象和对象通过发消息,通知做什么。如对象——电池通知对象——电动机做动作对象是由其他类型的对象组成的存储区每一个对象都属于一个特定的类型同类型的对象,都能接收相同的消息。

1.2类型

 人类认识世界的过程就是面向对象的(猫、房子等事物)人类认识世界的过程就是由具体到抽象(比如,小孩刚出生,见过真狼之后才会对狼有一种概念;我们对炼钢工厂真实考察过之后,才能抽象出炼钢的程序)类型具有共同特征的对象,这些对象属于同一共同类别;类型是类别的抽象;对象是类型创建的具体变量;类型刻画就是抽取对象的共同特征与行为好,看一个例子你就明白了类型、对象、抽象这几个概念了!
#include <iostream>
using namespace std;struct Student{/*特征*/string name;string sno;int score;/*行为*/void learn(string par){cout << "learn" << par << endl;//学生学什么}void eat(string par){//学生吃什么cout << "eat" << par << endl;}};
int main(){Student one;one.name = "Zhangsan";one.sno = "A07160289";one.score = 188;one.learn("English");one.eat("米饭");Student two;two.name = "Lisi";two.sno = "A07160300";
}
来了一个需求:要你写出学生的特征和行为信息。
我们根据对学生的实际考察,抽取学生的共同特征与行为(学生都有名字、学号、分数的特征以及学什么、吃什么的行为),我们据此,抽象出一个学生类型,即定义了一个struct Student{}结构体类型,
而我们用结构体定义的两个学生(变量):Zhangsan、Lisi就是对象。

二、如何在计算机中描述类型

2.1使用结构体(struct)对类型进行描述

 如1.2中的程序例子所示。再写一个例子:(设置一个时钟,并给其设置一个初始时间)
/*下例的struct Mytime{}是类,mt是对象*/
#include <iostream>
#include <cstdio>
#include <iomanip>
using namespace std;
struct Mytime{int hour;int min;int sec;void show(){cout << setfill('0') << setw(2) <<hour << ":" << setw(2) << min << ":"<< setw(2) << sec << '\r' << flush;}void dida(){sleep(1);if(60 == ++sec){sec = 0;if(60 == ++min){min = 0;if(24 == ++hour){hour = 0;}}}}void run(){while(1){show();dida();}}}; int main(){Mytime mt;mt.hour = 9;mt.min = 28;mt.sec = 35;mt.run();
}

2.2使用类(class)对类型进行描述

 类内成员默认是私有的privateprivate只能在类内访问,不让外界访问所谓类内是指在class Student{};大括号之内public可以在类内和类外访问private、public权限修饰范围:从一个权限开始 到 下一个权限的开始在c++中,如果类的成员只是变量而无函数,且变量公开,则我们一般使用struct,否则,我们一般使用class。二者没啥区别)程序举例:(把上例的struct改为class,并添加private、public权限)
#include <iostream>
#include <cstdio>
#include <iomanip>
using namespace std;
class Mytime{public:int hour;int min;int sec;private://设置show()、dida()为类内私有void show(){cout << setfill('0') << setw(2) <<hour << ":" << setw(2) << min << ":"<< setw(2) << sec << '\r' << flush;}void dida(){sleep(1);if(60 == ++sec){sec = 0;if(60 == ++min){min = 0;if(24 == ++hour){hour = 0;}}}}public:void run(){while(1){show();dida();}}};  int main(){Mytime mt;mt.hour = 9;mt.min = 28;mt.sec = 35;mt.run();
}
 程序再改进:(把时间的初始化挪到类内,并将hour、min、sec私有化)
#include <iostream>
#include <cstdio>
#include <iomanip>
using namespace std;
class Mytime{private:int hour;int min;int sec;private://设置show()、dida()为类内私有void show(){cout << setfill('0') << setw(2) <<hour << ":" << setw(2) << min << ":"<< setw(2) << sec << '\r' << flush;}void dida(){sleep(1);if(60 == ++sec){sec = 0;if(60 == ++min){min = 0;if(24 == ++hour){hour = 0;}}}}public:void run(){while(1){show();dida();}}void initMytime(){mt.hour = 9;mt.min = 28;mt.sec = 35;}};   int main(){Mytime mt;mt.initMytime();//mt.hour = 9;//mt.min = 28;//mt.sec = 35;mt.run();
}
我们改进的这个程序,通过调用类型中的public函数mt.initMytime()
实现了对类内私有变量hour、min、sec的初始化。
但是,如果我们不小心重复初始化了呢?比如不小心重复调用了
mt.initMytime(),因此对于类内成员的初始化我们一般不这样写,
我们使用构造函数。见下节。

三、构造函数

3.1构造函数概述

概念:创建一个对象时,编译器自动帮你调用一次,并且仅仅调用一次
创建 构造函数的条件:和类名相同没有返回值类型
目的是:初始化对象
如2.2第二个例子中的:
void initMytime(){mt.hour = 9;mt.min = 28;mt.sec = 35;}改为:class Mytime{省略代码......Mytime(){mt.hour = 9;mt.min = 28;mt.sec = 35;}
};
int main(){Mytime mt;//mt.initMytime();//mt.hour = 9;//mt.min = 28;//mt.sec = 35;mt.run();}
 这就行了。注意,你不用再调用Mytime()进行初始了化。编译时编译器自动帮你执行Mytime()进行初始化。并且仅仅调用一次。

3.2一个知识点

int main(){Mytime mt;//在栈中申请mtMytime mt2();//这不是申请类mt,这是函数的声明,因此不能随意加括号Mytime *pt = new Mytime;//在堆中申请一块内存Mytime *pt2 = new Mytime();//在堆中申请一块内存mt.run();
}

四、一个对象创建的过程

第一步:根据类型的大小进行分配内存;
第二步:进行处理成员变量①如果成员是基本类型(int、double等)的数据,编译器就什么都不做②如果成员是类类型的成员,则构建这个成员。也就是说,第一步不是已经分配好了一块内存了吗,现在在这片内存里面开辟出一片空间给这个类类型的成员。
第三步:调用这个类型的构造函数。概念有点抽象,我们来写个程序:
#include <iostream>
using namespace std;
class Data{private:int year;int month;int day;public:Data(){cout << "Data's_构造函数" << endl;year = 2020;month = 8;day = 20;}void show(){cout << year << "-" << month << "-" << day<< endl;}
};
class Person{double salary;Data data;public:Person(){cout << "Person's_构造函数" << endl;}void show(){data.show();cout << salary << endl;//salary没有初始化,会输出一个垃圾数}};    int main(){/*Data data;data.show();要点一:构造函数Data()对year、month、day进行了初始化。如果你不对year、month、day进行初始化,那么输出的year、month、day会是垃圾数*//*要点二:类Person中的一个成员是类Data data*/Person p;p.show();/*运行结果:Data's_构造函数Person's_构造函数2020-8-202.07368e-317*/}

五、构造函数的应用

5.1 要点

 要点一:构造函数可以设计参数,可以有多个构造函数,能形成重载关系。一旦提供构造函数,则系统提供的默认构造函数就会自动消失。要点二:可以利用参数的默认值简化构造函数的个数;程序示例:
#include <iostream>
using namespace std;
class A({public:A(){}A(int x){cout << "A(int)" << endl;}A(int x, double y){}
};int main(){A a(111);//一:这个111就是传参,传递给构造函数;//二:A a(111);编译器不会理解成函数声明。函数声明里没有带111数值的是吧。A b;A c(1,1.5);/*以上三个类的定义都能够编译通过,形成重载机会*//*看,上面例子咱们定义了三个构造函数,其实咱们之前学过函数参数的默认值吧,可以利用函数参数默认值,从而把构造函数的个数缩减为一个。比如上面的这个例子就可以只要构造函数A(int x = 0, double y = 0.0){}*/A *pa = new A(100,20.5);//100,20.5给构造函数传参
}

5.2 初始化列表

 如果类中有const类型的成员 或者 引用类型的成员,则使用初始化参数列表是一个不二的选择。初始化参数列表的位置是在构造函数参数列表(即构造函数的()里面的东东)之后,实现体(即构造函数的{}里面的东东)之前。初始化参数列表的作用是:保证参数初始化在构造函数执行之前被调用程序举例:
#include <iostream>
using namespace std;
int g_var = 188;
class A({const int x;//const修饰,则必须初始化参数列表,否则编译失败int y;int& z;//引用类型变量,则必须初始化参数列表,否则编译失败public:A():x(100),y(199),z(g_var){/*初始化参数列表只能在构造函数的()和{}之间;const修饰的和引用类型的成员都必须初始化参数列表。其他类型的成员无此限制*/   //这里的:x(100)就是给x赋初值100。当然你要是给y初始化也没啥问题//对z初始化,z为g_var别名}void show(){cout << x << ":" << y << endl;//x=100;y=199}
};
int main(){A a;a.show();
}

六、头文件和实现文件的分离

在实际开发中头文件和实现文件要分离
背景知识:首先你要直到什么是声明、定义、extern,去看这篇文章:

https://blog.csdn.net/weixin_45519751/article/details/108142857
程序举例:
mytime.h文件

#ifndef MYTIME_H
#define MYTIME_H
/*在c++的头文件中只能进行变量的声明、函数的声明,类的定义*/
extern int g_var;//变量声明而非定义。必须要有extern
void show();//函数声明
class Mytime{//类的定义private:int hour;int min;int sec;public:Mytime(int hour=0,int min=0,int sec=0);void show();void dida();void run();};
#endif
 mytime.cpp文件
#include "mytime.h"
#include <iostream>
#include <iomanip>
#include <unistd.h>
using namespace std;
void show(){cout << "g_var" << g_var << endl;
}/*来自于类中的函数,前要加上  类名:: */
Mytime::Mytime(int hour,int min,int sec):hour(hour),
min(min),sec(sec){/*解释一下hour(hour)第一个hour是类的成员变量,第二个hour是构造函数的参数,hour(hour)即把0赋值给成员变量hour咱们这里只不过让类的成员变量hour与构造函数的参数hour重名了而已*/
}
void Mytime::show(){cout << setfill('0') << setw(2) << hour << ":" <<setw(2) << ":" << min << ":" << setw(2) << sec << '\r' << flush;
}
void Mytime::dida(){sleep(1);if(60 == ++sec){sec = 0;if(60 == ++min){min = 0;if(24 == ++hour){hour = 0;}}}
}
void Mytime::run(){::show();//这里调的全局函数show()while(1){show();//这里调的是类中的成员函数dida();//这里调的是类中的成员函数}
}
 testmytime.cpp文件
#include "mytime.h"
int g_var = 100;//这里是定义int main(){Mytime mt;mt.run();
}
 运行结果:lioker:Desktop$ g++ ./*.cpplioker:Desktop$ ./a.out g_var10000:0:01

七、this指针

7.1 this指针概述

 在构造函数中this代表正在被构建的对象的地址在成员函数中,this指向调用这个函数的对象的地址。程序举例:
#include <iostream>
using namespace std;
class Mytime{int hour;int min;int sec;public:Mytime(int hour=0,int min=0,int sec=0){/*对hour赋上构造函数参数值0,可以用初始化参数列表但我们这里用this指针的方法实现*/this->hour = hour;this->min = min;this->sec = sec;}void show(){cout << "show()" << this << endl;//打印show()的this地址cout << this->hour << ":" << this->min << ":" << this->sec << endl;}
};
int main(){Mytime mt;cout << "main mt=" << &mt << endl;mt.show();
}
 运行结果:lioker:Desktop$ g++ this.cpp lioker:Desktop$ ./a.out main mt=0x7ffe788792e0show()0x7ffe788792e00:0:0总结:this就是类的一个对象的地址;当this指向mt这个对象时是一个地址,指向另一个对象就是另一个地址了

7.2 this的使用

 ①用在函数的参数上②用于成员函数的返回值程序举例:
#include <iostream>
using namespace std;
/*声明类型Data 和 函数show()*/
class Data;
void show(Data *data);
/*写一个日期类型*/
class Data{ public:int year;int month;int day;public:Data(int year=0,int month=0,int day=0){this->year = year;this->month = month;this->day = day;}void showSelf(){show(this);//this作为参数。}/*写一个成员函数,作用:调用一次day就加一*/Data* addOneDay(){day++;return this;/*这里的this就是对象data的地址,你把它返回,再->addOneDay(),就相当于调用了两次addOneDay()函数,即++day两次.即day=2*/}/*写法二:Data addOneDay(){day++;return *this;/*这里的*this就相当于你把data复制了一份。你把它这个复制的部分返回了,再addOneDay()(注:main函数中语句改为data.addOneDay().addOneDay();),其实是对复制的data中的day++而非data本身++。也就是day只加了一次,即day=1*/}*//*写法三:Data& addOneDay(){day++;return *this;/*这里的*this就是对象data的值,(Data&引用即返回的还是data本身)。再.addOneDay()(注:main函数中语句改为data.addOneDay().addOneDay();),其实是对data中的day++。也就是day加了2次,即day=2*/}*/};
/*写一个全局函数show()显示一个日期*/
void show(Data *data){cout << data->year << "-" << data->month <<"-" << data->day << endl;
}
int main(){Data data;data.showSelf();data.addOneDay()->addOneDay();//则day变为2(++2次)data.showSelf();
}

八、析构函数

8.1概述

 析构函数和类型名相同,但函数名前有一个~在对象销毁之前,系统(编译器)自动调用一次析构函数析构函数是无参的;一个类型只有一个析构函数作用是:即在对象销毁之前,做一些清理工作

8.2析构函数程序举例:

(利用析构函数释放掉在构造函数中建立的堆内存)

#include <iostream>
using namespace std;
class A{int *parr;public:A(int size=0){parr = new int[size];//分配堆内存;可以在析构函数里释放掉cout << "A()" << endl;}~A(){detele[] parr;//释放掉parr堆内存parr=NULL;cout << "~A()" << endl;}
};  int main(){/*A *parr = new A[5];delete[] parr;/*运行结果:5个A(),5个~A()*/A a(10);
}

【C++】day03 - 【类型与对象的概念】【类型】【构造函数】【一个对象创建的过程】【构造函数的应用】【头文件和实现文件的分离】【this指针】【析构函数】相关推荐

  1. c#反射,类型XX对象无法转换为类型XX,XX是一样的问题

    //创建数据类 object objVoucherReverse = System.Reflection.Assembly.LoadFrom(AppDomain.CurrentDomain.BaseD ...

  2. java new 新对象_java基础(五)-----new一个对象的具体过程

    在创建对象之前,首先要判断类有没有被加载,例如创建对象或调用类的static方法变量时,会触发类加载,如下: Dog dog = new Dog(); 首次访问某个类的静态方法或者静态字段时: Dog ...

  3. 数分笔记整理7 - Pandas Pandas - DataFrame类型的对象 - 创建方式

    DataFrame类型 DataFrame是一个多维数据类型.因为通常使用二维数据,因此,我们可以将DataFrame理解成类似excel的表格型数据,由多列组成,每个列的类型可以不同. 因为Data ...

  4. 复合类型_没有学不会的python--复合类型(1)--概念和元组

    其实复合类型并不复杂,对于没有学习过python的朋友来说,完全不用担心. 复合类型是什么? 前面我们有讲述过简单数据类型,由于我在多个平台都有上传文章,所以这里就不贴出链接来了,烦请有需要的朋友自己 ...

  5. JS中数据类型、内置对象、包装类型对象、typeof关系

    平时在复习JS基础知识时,经常会遇到JS数据类型.基础数据类型.内置对象.包装类型对象,检测数据类型时,用到的typeof值,感觉都差不多,但是又有差异.今天特地整理下,方便理解. JS数据类型 基础 ...

  6. java vo转map_javabean实体类对象转为Map类型对象的方法(转发)

    //将javabean实体类转为map类型,然后返回一个map类型的值 public static Map beanToMap(Object obj) { Map params = new HashM ...

  7. java 返回类对象_JAVA如何实现返回不同类型的对象

    JAVA如何实现返回不同类型的对象 发布时间:2020-11-10 16:11:51 来源:亿速云 阅读:96 作者:Leah 这篇文章运用简单易懂的例子给大家介绍JAVA如何实现返回不同类型的对象, ...

  8. linux下进程的模式和类型如何,Linux——基础概念和命令

    Linux文件存储结构: /  :(根目录)根目录下的存储结构 /bin :命令对应的可执行文件 /home:(普通用户的家目录)-> username(多个用户) /boot: 系统开机使用的 ...

  9. C语言基本概念----类型

    本文来源微信公众号文章,点击进入 存储在对象中的值或由函数返回的值,其含义由访问它的表达式的类型决定.声明为对象的标识符是最简单的表达式,其类型就是声明时为标识符指定的类型.类型(types)分为对象 ...

最新文章

  1. H.265视频编码与技术全析(下)
  2. [MOSS开发]:WSS v3授权
  3. cad2020 开始_如何设置CAD2020经典模式,原来这么简单,一起来看看
  4. 什么是带宽?—Vecloud微云
  5. Matlab实用程序--图形应用-图形标注
  6. mint java_Linux Mint19安装jdk1.8.0.191过程
  7. 云原生下,如何实现高可用的MySQL?
  8. 人造卫星为什么会绕着地球转而不是停在太空中或者越飞越远.掉进地球的卫星为什么烧不完....
  9. AGC004(A~E)
  10. 码农30岁后的体检——你最需要的是直面的勇气
  11. 项目四管理计算机中的资源,第十七章-计算机在项目管理中的应用PPT课件.ppt
  12. 计算机学会a类论文是sci吗,什么是SCI、EI、CCF、DASFAA
  13. Jquery图片轮播(连续滚动+突出显示)
  14. Sqli-labs之Less-17
  15. jQuery取值和赋值的基本方法
  16. Lightroom Classic 9.0安装教程
  17. 厦门→世界各地国际快递业务
  18. 好用的磁盘清理软件Disk Diet for mac安装教程及功能介绍
  19. 腾讯技术团队整理,年度好文轻松彻底入门 Flutter,秒变大前端
  20. Android TextView长按选择复制工具类

热门文章

  1. PHPCMS V9系统配置文件和模板目录
  2. [转载]欧洲杯四强之魔兽争霸版
  3. 配置machineKey
  4. C++凯撒密码加密解密算法
  5. JAVA代码无效化快捷键_Eclipse常用快捷键及快捷键功能失效时的解决方案
  6. MVC框架的Model数据验证
  7. 业务架构、数据架构、应用架构、技术架构对比
  8. 【删除数组中重复的元素】
  9. RPA(影刀)无需写代码抓取某东的商品信息
  10. WCDMA物理层中的基本概念