0.0 从程序结构上看:

  基于过程的程序中:围绕功能进行的,函数是构成程序的基本部分,程序面对的是一个个函数。

  面向对象的程序中:除主函数外,其他函数基本上都出现在“类”中,只有通过类才能调用类中的函数。程序的基本构成单元是类,程序面对的是一个一个的类和对象。
  面向对象程序设计四个主要特点:抽象、封装、继承和多态性。

PS:面向过程的程序设计思路更像是数学解题,分清步骤,先做什么,再做什么。
面向对象的程序设计思路更偏向现实,分别设计细节,最终在进行组装。

1.0 对象:

万物皆可看做对象。对象是构成系统的基本单元。
若以一个班级作为一个对象,有两个要素。
一、静态特征:班级所属专业、人数、教师等(称为属性)。
二、动态特征:学习、开会、体育比赛等(称为行为或功能,在程序设计中也称为方法)。
       若想从外部控制学生活动,则可从外界对班级发信息,如打铃就是下课(称为消息)。
消息的作用:对对象的控制。


  1.任一对象都应具有两要素:属性(attribute)和行为(behavior)。
  2.对象是由一组属性和一组行为构成的。
  3.一个系统中的多个对象通过一定渠道相互联系,要使某一个对象实现某一种行为(即操作),应当向它传送相应的消息。
  4.每个对象都是由数据(体现了属性)和函数(即操作码,对数据进行操作)。

几个名词:
方法类的成员函数在面向对象程序理论中被称为“方法”,指的是对数据的操作
消息:其实就是一个命令,由程序语句来实现。

2.0 面向对象程序设计 四个主要特点

2.1 抽象

  抽象的作用:表示同一类事物的本质
  类是对象的抽象,而对象则是类的特例,即类的具体表现形式。

2.2 封装与信息隐蔽

  可以对一个对象进行封装处理,把它的一部分属性和功能对外界屏蔽,也就是说从外界是看不到的、甚至是不可知的。

封装性(encapsulate):
  一、是将有关的数据和操作代码封装在一个对象中,形成一个基本单位,各个对象之间相对独立,互不干扰。
  二、将对象中某些部分对外隐蔽,即隐蔽其内部细节,只留下少量接口,以便与外界联系,接收外界的消息。(信息隐蔽,有利于数据安全,防止无关的人了解和修改数据)。

2.3继承与重用

  若每设计一个事物都要从头写不是很麻烦,所以一般不会全部从头设计,而是选择在有一个事物的基础上,在继续增加一些新功能。这就是面向对象程序设计中的继承机制。
  如:大家都清楚了马的特征,若要叙述“白马”的特征,显然无需从头介绍,只需说:白马是白色的马即可。这边的“白马”(子类或派生类)继承了“马”(父类)的基本特征,又增加了新的特征(颜色)。
而这就是常说的“软件重用”(software reusability)的思想。

2.4多态性

  多态性(polymorphism):由继承而产生的不同的派生类,其对象对同一消息会作出不同的响应。
  若几个相似而不完全相同的对象,有时人们要求向它们发出同一个消息时,它们的反应各不相同,分别执行不同的操作。这种情况就是多态现象
  如:甲乙丙三个同学,他们都是高二年级,具有基本相同的属性和行为,在同时听到上课铃声时,会分别走向三个不同的教室。
面向对象程序设计的特点:
把数据和有关操作封装成一个对象。

3.0 程序设计者的任务包括:

一、设计所需的各种类和对象(决定把那些数据和操作封装在一起)。
二、考虑怎样向有关对象发送消息,以完成所需的任务。

类是C++的灵魂,基于对象的程序是以类和对象为基础的,程序的操作是围绕对象进行的。

面向对象的程序设计中对象:程序中的每一组数据都是有特定用途的,是为某种操作而准备的,也就是说,一组数据是与一组操作相对应的。因此人们把相关的数据和操作放在一起,形成一个整体,与外界相对分隔。

程序设计的关键:设计好每一个对象以及确定向这些对象发出命令,使各对象完成相应的操作。

面向对象的软件工程:
1.面向对象分析(Object Oriented Analysis,简称:OOA)
2.面向对象设计(Object Oriented Design,简称:OOD)
3.面向对象编程(Object Oriented Programming,简称:OOP)
4.面向对象测试(Object Oriented Test,简称:OOT)
5.面向对象维护(Object Oriented Soft Maintenance,简称:OOSM)

4.0 类

4.1类的定义

类(class):代表了某一批对象的共性和特征。
  类是对象的抽象,而对象是类的具体实例
  对象是类的一个变量类是对象的模版,是用来定义对象的一种抽象类型。

struct Student      /声明了一个名为Student的结构体类型,可以看到它只包括数据(变量),没有包括操作
{int num;char name[20];char sex;}; Student stud1,stud2;         /定义了两个结构体变量stud1,stud2
class Student            /class开头,类名Student,把数据和操作封装在一起
{int num;                /{类体 class body}char name[20];char sex;void display()         /成员函数{cout<<"num :"<<num<<endl;cout<<"name :"<<name<<endl;cout<<"sex :"<<sex<<endl;}};Student stud1,stud2;    /定义了两个Student类的对象stud1和stud2

  现在封装在类对象stud1和stud2的成员都对外界隐蔽,外界不能调用。只有本对象中的函数display可以引用本对象中的数据。也就是说,在类外不能直接调用类中的成员
  这就相当安全了,但在程序中怎样才能执行对象stud1和display函数呢?现在是无法启动,因为缺少对外界的接口,外界不能调用类中的成员函数,完全与外界隔绝了。很显然这样的类是毫无实际作用的。
  因此,一般是把数据隐蔽起来,而把成员函数作为对外界的接口。譬如:可以从外界发出一个命令,通知对象stud1执行其中display函数,输出某一学生的有关数据。
  注意:一个类应当至少有一个公用的成员函数,作为对外的接口,否则就无法对对象进行任何操作。

class Student                         /声明类Student
{private:                            /声明以下部分为私有的int num;  char name[20];char sex;public:void display()                       /成员函数{cout<<"num :"<<num<<endl;cout<<"name :"<<name<<endl;cout<<"sex :"<<sex<<endl;}};Student stud1,stud2;                /定义了两个Student类的对象stud1和stud2

现在声明了display函数是公用的,外界就可以调用该函数。
====》类的声明本身并不能修改程序的行为,必须使用类,也就是像函数那样去调用。也就是将类变为对象(类的实例),并通过对象访问成员方法和属性。

若类定义中没有private(私有的)和public(公用的),则系统就默认为私有的。

4.2 类的声明的一般形式

对类类型的声明的一般形式为:
  class 类型
  {private:
     私有的数据和成员函数;
   public:
     公用的数据和成员函数l
  }

4.3 成员访问限定符:

private(私有的):只能被本类中的成员引用,类外不能调用(友元类除外)
public(公用的):可被本类中的成员函数所引用,也可被类的作用域内的其他函数引用(外界可调用)
protected(受保护的):不能被类外访问(但可被派生类的成员函数访问)

访问属性 属性 对象内部 对象外部
public 公有 可访问 可访问
protected 保护 可访问 不可访问
private 私有 可访问 不可访问

====》struct 中所有的行为和属性都是public的(默认)。

4.4 定义对象的三种方法

一、先声明类类型,然后再定义对象:(一般采用该方法)
定义对象的两种形式:
(1)class 类名 对象名;
(2)类名 对象名;
二、在声明类的同时定义对象:(跟结构体类似)
三、不出现类名,直接定义对象:

4.5 在类外定义成员函数:

“::”:作用域限定符(或称作用域运算符):用它声明函数是属于哪个类的

void Student::display()               /在类外定义display类函数(注意必须加上类名){cout<<"num :"<<num<<endl;cout<<"name :"<<name<<endl;cout<<"sex :"<<sex<<endl;}                               /注意:类函数必须现在类体中作原型声明,然后在类外定义/也就是说类体的位置应在函数定义之前,否则编译时会出错

4.6 内置成员函数(inline):可省略inline

  注:若成员函数不在类体内定义,而在类体外定义,系统并不把它默认为内置函数,调用这些成员函数的过程和调用一般函数的过程是相同的。
  在函数的声明时或函数的定义时做inline声明均可(二者选其一)。
  若类外定义inline函数,则必须将类定义的成员函数的定义都放在同一个头文件(或写在同一个源文件中),否则编译时无法进行置换(将函数代码的拷贝嵌入到函数调用点)。

4.7 成员函数的存储方式:

  同一类的不同对象中的数据成员的值一般是不相同的,而不同对象的函数的代码是相同的,不论调用哪一个对象的函数的代码,其实调用的都是相同内容的代码。故有一个公用函数代码区域
  一个对象所占的空间大小只取决于该对象中数据成员所占的空间,而与成员函数无关。
  提问:不同的对象使用的是同一个函数代码段,它怎么能够分别对不同对象中的数据进行操作呢?
  回答:C++为此专门设立了一个名为this的指针,用来指向不同的对象。
  说明:
  (1)不论成员函数在类内定义还是在类外定义,成员函数的代码段的存储方式是相同的,都不占用对象的存储空间。
  (2)不要将成员函数的这种存储方式和inline函数的概念混淆。

4.8访问对象中的成员可以有三种方法:

方法一:通过对象名和成员运算符访问对象中的成员;
方法二:通过指向对象的指针访问对象中的成员;
方法三:通过对象的引用访问对象中的成员。

  一般形式:
    对象名.成员名          “.”是成员运算符

====》①普通定义的类,使用成员运算符(.)。
   ②new出来的实例,使用指针运算符(->)。

5.0 接口与实现

当接口与实现(对数据操作)分离时,只要类的接口没有改变,对私有实现的修改不会引起程序的其他部分的修改。
声明头文件是用户使用类库的公用接口
包含成员函数定义的文件就是类的实现
类声明和函数定义是分别放在两个文件中。

6.0 一个C++程序是由三部分组成:

一、类声明头文件(后缀.h);(系统提供的只包括成员函数申明,不包括定义)
二、类实现文件(后缀.cpp),包含类成员函数的定义;
三、类的使用文件(后缀.cpp),即主文件。
类库包括两个组成部分:
(1)包括类声明的头文件。
(2)已经过编译的成员函数的定义,它是目标文件。

7.0 构造函数:

  作用:处理对象的初始化
  是一种特殊的成员函数,与其他成员函数不同,无需用户来调用它,而是在建立对象时自动执行
注意:
  构造函数的名字必须与类名同名,而不能任意命名,以便编译系统能识别它并把它作为构造函数处理。不具有任何类型,不返回任何值一经使用,默认将不复存在

对象的初始化
  就是对数据成员赋初值,对象代表一个实体,每个对象都有它确定的属性。
注意:
  不要试图在声明类时对数据成员初始化。因为类并不是一个实体,而是一种抽象类型,并不占存储空间,显然无处容纳数据。

7.1 情景一:所有成员为公用

若类中所有成员为公用,则定义对象时可对数据成员进行初始化。
若数据成员有私有的,或类中有private或protected的数据成员则不可用此方法。

class Time
{public:hour; minute;sec;
};
Time t1 ={14,56,30};                        /将t1初始化为14:56:30

7.2 情景二:无参构造函数

使用构造函数(一种特殊的成员函数,与其他成员函数不同,不需要用户来调用它,而是在建立对象时自动执行)来处理对象的初始化。
注意:构造函数名字需与类名同名,不可任意命名,不具有任何类型,不返回任何值。

class Time
{public:Time()                     /也可以在类中声明,在类外定义{hour=0; minute=0;sec=0;}  /没有类型,只是为了初始化,故不需要在定义构造函数时进行声明类型。private:int hour; int minute; int sec;
};
int main()
{Time t1;                   /建立对象t1,同时调用构造函数t1.Time()Time t2  = t1;                /建立对象t2,并用一个t1初始化t2   用一个类对象初始化另一个类对象
}

  这边不要误认为是在声明类时直接对程序数据赋初值(这是不允许的),赋值语句写在构造函数的函数体中,只有在调用构造函数时才执行这些赋值语句。
  若用户没有定义构造函数,系统会自动生成一个,只是该构造函数的函数体是空的,没有参数,不执行初始化。

7.3 情景三:带参构造函数

  带参数的构造函数。在调用不同对象的构造函数时,从外面将不同的数据传递给构造函数,以实现不同的初始化。
构造函数首部的一般形式为
构造函数名(类型1 形参1 ,类型2 形参2 ,…)

定义对象的一般形式为
类名 对象名(实参1,实参2,…)

class Box
{public:Box(int,int,int){  }private:int hight;int width;int length;
}
Box::Box(int h,int w,int len){height=h;width=w;length=len;}
int main()
{Box box1(12,25,30)
}

7.4 情景四:参数初始化表

参数初始化表来实现对数据成员的初始化。
这种方法不再函数体内对数据成员初始化,而是在函数首部实现。

Box::Box(int h,int w,int len):height(h),width(w),length(len) { }

在上例函数首部末尾加冒号,然后列出参数初始化表
表示:形参h的值初始化数据成员height…
若数据成员是数组,则应当在构造函数的函数体中用语句对其赋值,而不能在参数初始化表中对其初始化。

7.5 情景五:拷贝构造函数(赋值构造函数)

由已存在的对象,创建新的对象,也就是说新对象,不由构造器来构造,而是由拷贝构造器来完成。拷贝构造器也是固定的

class Box
{public:Box(const Box &another) { }           /Box为类名,another为已存在的对象private:int hight;int width;int length;
}

应用场景:

7.5.1 场景一:

int main(){Test t1(10) ;//这里第一个应用场景Test t2 = t1;                        /用对象t1初始化对象t2
}

7.5.2 场景二:

int main(){Test t1(10) ;//这里第二个应用场景Test t2(t1);                      /用对象t1初始化对象t2
}

7.5.3 场景三:

#include<iostream>
class Location{public:Location(int xx = 0;int yy = 0)             /带参构造函数{X=xx;   Y==yy;   cout<<"Constructor Object"<<endl;}Location(const Lacation &obj)               /拷贝构造函数{X=obj.x; Y=obj.Y;  cout<<"Copy Constructor"<<endl;}~Location()                                  /析构函数{cout<<X<<","<<Y<<"Object destroyed."<<endl;}int GetX() {  return X; }private:int X,Y;
};
void func(Location p)                           /会执行p=b的操作,p会调用拷贝构造函数进行初始化
{   cout<<"func begin"<<endl;   cout<<p.GetX()<<endl;   cout<<"func end"<<endl;   }void test()
{   Location a(1,2);                            /对象a调用 带参构造函数 进行初始化Location b=a;                               /对象b调用 拷贝构造函数 进行初始化//注意区分下面这种情况:若改成下面这样,则不会调用拷贝构造函数。//Location b;//b=a;cout<<"-----"<<endl;func(b);                                    /b实参去初始化形参p,会调用拷贝构造函数。
}
int main(){test() ;return 0;
}

====》其实就是:当有多个构造函数时,按照对应格式进行匹配。

7.6 构造函数重载:

系统怎么辨别调用哪个构造函数呢?
编译系统是根据函数调用的形式去确定对应哪个构造函数。

注意:
  构造函数是不能被用户显式调用的。
  一个类只能有一个默认构造函数,也就说,可以不用参数而调用的构造函数,一个类只能有一个。

使用默认参数的构造函数
应该在什么地方指定构造函数的默认参数?
应在声明构造函数时指定默认值,而不能只在定义构造函数时指定默认值。
原因:
  因为类声明是放在头文件中的,它是类的对外接口,用户是可以看到的。
  函数的定义是类的实现细节,用户往往是看不到的。
  在声明构造函数时指定默认参数值,使用户知道在建立对象时怎样使用默认参数。

8.0析构函数(destructor):

  作用与构造函数相反,它的名字是类名前加上“~”。
当对象的生命周期结束时,会自动执行析构函数,具体为以下四种情况:
情况一
  若在一定函数中定义了一个对象(假设是自动局部对象),当这个函数被调用结束时,对象应该释放,在对象释放前自动执行析构函数。
情况二
  静态局部对象在函数调用结束时对象并不释放,因此不调用析构函数,只在main函数结束或调用exit函数结束程序时,才调用static局部对象的析构函数。
情况三
  若定义了一个全局的对象,则在程序的流程离开其作用域时(如main函数结束或调动exit函数)时,调用该全局的对象的析构函数。
情况四
  若用new运算符动态地建立了一个对象,当delete运算符释放该对象时,先调用该对象的析构函数。

析构函数的作用:
  并不是删除对象,而是在撤销对象占用的内存之前完成一些清理工作,使这部分内存可以被程序分配给新对象使用。
  用来执行用户希望在最后一次使用对象之后所执行的任何操作。
注意:
  不返回任何值,没有函数类型,没有函数参数(故不能被重载)。
  一个类可有多个构造函数,但只能有一个析构函数。

包含构造函数和析构函数的C++程序

class Student
{public:Student(int n,string nam,char s) //定义有参数的构造函数{num = n;name = nam;sex = s; cout<<"Constructor called."<<endl;}~Student()   //定义析构函数{cout<<"Destructor called."<<endl;}void display(){cout<<"num:"<<num<<endl;cout<<"name:"<<name<<endl;cout<<"sex:"<<sex<<endl;}private:int num; char name[10];char sex;
};
int main()
{Student stud1(10010,"Wang_li",'f'); std1.display();return 0;}

运行结果:

Constructor called.
num:10010
name:Wang_li
sex:fDestructor called.

析构函数相当于一个栈,先进后出。先构造的后析构,后构造的先析构。(这是对同类存储类别的对象而言的)

类和对象的特性(C++谭浩强第三版笔记)相关推荐

  1. C程序设计-谭浩强 第三版-学习笔记 第2章 程序的灵魂 算法

    第 2 章 算法 --程序的灵魂 程序 = 算法 + 数据结构 (沃思,计算机科学家) 一个程序应该包括两方面: 对数据的描述:在程序中要指定数据的类型和数据的组织形式,即数据结构(data stru ...

  2. C语言谭浩强第三版第九章例题及课后题:预处理命令

    目录 9.1定义一个带参数的宏,使两个参数的值互换 9.2输入两个整数,求它们相除的余数 9.3求三角形面积 9.4(5)判断闰年 9.5分析下面的宏所定义的输出格式 9.6设计输出实数的格式 9.7 ...

  3. C语言谭浩强第三版第十二章例题及课后题:位运算

    eg12.1取一个整数a从右端开始的4~7位 0000...000000        0 1111...111111       ~0  1111...110000       ~0<< ...

  4. C程序设计-谭浩强 第三版-学习笔记第1章 C语言概述

    第一章 C语言概述 1.C语言历史背景 C语言是在B语言的基础上发展起来的,兼具一般高级语言和低级语言的优点,可用来编写系统软件或应用软件. 1972-1973年,贝尔实验室在B语言基础上设计出C语言 ...

  5. C程序设计(谭浩强第五版)总结

    C程序设计(谭浩强第五版)总结 本篇文章主要是总结谭浩强第五版C语言书上的重点和易漏点的知识点,其目的主要是给高校期末考试的同学们点参考.本文所参考的书籍是谭浩强的<C程序设计(第五版)> ...

  6. 《C语言程序设计》(谭浩强第五版) 第2章 算法——程序的灵魂

    <C语言程序设计>(谭浩强第五版) 第2章 算法--程序的灵魂 习题解析与答案 你也可以上程序咖(https://meta.chengxuka.com),打开大学幕题板块,不但有答案,讲解 ...

  7. C程序设计谭浩强第五版课后答案 第三章习题答案

    C语言程序设计谭浩强第五版课后答案第三章 1.假如我国国民生产总值的年增长率为7%, 计算10年后我国国民生产总值与现在相比增长多少百分比.计算公式为p=(1+r)np = (1+r)^np=(1+r ...

  8. C语言程序设计(谭浩强第五版)——习题

    C语言程序设计(谭浩强第五版)--习题 第3章 最简单的C程序设计--顺序程序设计 第4章 选择结构程序设计 第5章 循环结构程序设计 第6章 利用数组处理批量数据 第3章 最简单的C程序设计--顺序 ...

  9. 《C语言程序设计》谭浩强 第五版 编程10题解答2

    <C语言程序设计>谭浩强 第五版 编程10题解答2 11.素数计算 编写程序计算500-800区间内素数的个数cnt,并按所求素数的值从大到小的顺序,再计算其间隔减.加之和,即第1个素数- ...

最新文章

  1. ubuntu安装snort
  2. 弹出提示对话框并重定向网页
  3. mysql 优化300例_PHP+MySQL实现对一段时间内每天数据统计优化操作实例
  4. java char short区别_java 彻底理解 byte char short int float long double
  5. 云小课 | 大数据融合分析:GaussDW(DWS)轻松导入MRS-Hive数据源
  6. 分数加减法 http://acm.nyist.net/JudgeOnline/problem.php?pid=111
  7. 专注于分布式存储计算技术及其应用url http://www.nosqlnotes.net/
  8. DataFactory插入MySQL中文乱码问题
  9. web前端 基于html实现花店购物网站源码(HTML+CSS+JavaScript) 企业网站制作
  10. SkeyePlayer rtsp、rtmp低延迟播放器源码解析之64位编译方案
  11. matlab的hilbert变换的实现
  12. B站五面面经(附过程、答案)
  13. 终端上网_家里wifi上网很慢怎么办?通过这4招,让网速快到飞起来
  14. 移动端H5页面在ios设备上软键盘顶起页面后隐藏,页面不回弹的解决方案
  15. 一只兔子帮你理解 kNN
  16. 基于车辆运动学模型的LQR横向控制算法
  17. request:fail 发生了 SSL 错误无法建立与该服务器的安全连接——openssl报漏洞该升级了
  18. 小程序流量主怎么赚钱?
  19. linux的双系统修复工具下载,EasyBCD(系统引导修复工具)
  20. 怎么用python制作随机点名软件_python写一个随机点名软件的实例

热门文章

  1. 石昊独立高峰前, 其背如深渊, 其眼似苍穹
  2. php的cgi.fix_pathinfo解析
  3. 每日精选12条新闻 每天精选新闻早报简报
  4. Openlayers使用geoserver发布的图层
  5. postman高阶脚本
  6. Web页面右下角弹出窗口示例代码
  7. 联发科急于发展Android平台不被看好
  8. 如何把aac转化为mp3,4个处理方法教给你
  9. 证券业如何破局发展,用好NLP技术很关键
  10. 职场邮件 | 格式:姓名全拼(姓名全拼+城市缩写)