1、面向对象的基本概念
1、面向对象的概念
面向对象编程是一种程序设计的规范,他将对象作为程序的基本单位,将程序和数据封装在其中,以提高软件的重用性、灵活性和扩展性。对象指的是类的实例。面向对象的编程语言使程序能够较直观的反映客观世界的本来面目。所有面向对象的程序设计语言都支持对象、类、消息、封装、继承、多态等诸多概念。面向对象程序设计可以看作是种在程序中博阿寒各种独立而又互相调用的对象的思想。传统程序设计主张将程序看作是一系列函数的集合,或者一系列直接对计算机下达的指令。面向对象程序设计中的每一个小对象都应该能够接收数据、处理数据并将数据传达给其他对象。
1、类
类定义了意见事情的抽象特点、定义了事物的属性和它可以完成的动作(它的行为)。面向对象程序设计就是通过数据抽象,将许多实例中共性的数据和为操作这些数据所需要的算法抽取出来,并进行封装和数据隐藏,形成一个新的数据类型——“类”类型。
2、对象
对象是对问题领域中某个实体的抽象,是构成程序的基本单位和运行实体,是应用程序的组装模块,它可以是任何的具体事物。不同对象具有不同的特征和行为。在面向对象程序设计中,对象作为一个变量,包括数据和用来处理这些数据的方法和工具。
·· 类和对象就好比是“整数”和“123”,“整数”是一种数据的类型,而123是一个真正的“整数”(及对象)。所有的“整数”都具有“整数”所描述的属性,如“整数的大小”,系统则将内存分配个“整数“存储具体的数值。对象是程序可以控制的实体,包括属性、事件和方法。
3、属性
属性就是对象的特性,是用来描述对象特征的参数。属性是属于某一个类的,不能独立于类而存在。
4、方法
方法是指对象本省所具有的、反映该对象功能的内部函数或过程,亦即对象的动作。通俗的说,方法就是一个对象所执行的某些特定动作,如对象的移动、显示和打印等。其组织行为表现为过程和函数。
5、事件
事件泛指能被对象识别的用户操作动作或对象状态的变化发出的信息,亦即对象的响应。例如,在某个命令按钮上单击鼠标就会出现相应的程序代码,实现相应的功能,则单击鼠标就是一种事件。
2、面向对象的基本概念
1、封装性
封装是面向对象程序设计特征之一,是对象和类概念的主要特征。封装是把过程和数据包围起来,对数据的访问只能通过已定义的界面。封装保证了模块具有较好的独立性,使得程序维护修改较为容易。对应用程序的修改仅限于类的内部,因此可以将应用程序修改
带来的影响减少到最低限度。
2、继承
面向对象程序设计的最大优点是允许”继承“,即在某个类的基础上可以派生出来新类。一个新类可以从现有的类中派生,这个过程称为类继承。新类继承了原始类的特征,新类称为原始类的派生类(子类),而原始类称为新类的基类(父类)。派生类可以在它的基类那里继承方法和实例变量,而且类可以修改或者增加新的方法使之更适合特殊的需要。目前的面向对象程序设计开发工具都提供了大量的类,用户可以直接使用这些类,或通过对这些类的扩充和重用形成新的类。
3、多态性
多态性允许不同类的对象对同一个消息做出不同的响应。最常见的用法就是声明基类的指针,利用该指针指向任意一个子类对象,调用相应的虚函数,可以根据指向的子类不同而实现不同的方法。具体实现有静态多态性和动态多态性两种表现形式。静态多态性是通过一般的函数重载来实现的;动态多态性是通过虚函数来实现的。
2、类与对象
1、类的声明和对象的定义
类是具有相同特性对象的集合,类规定并提供了对象具有的属性特征和行为规则。对象通过类来产生,对象是类的实例。在C++语言中,类和对象的关系就是数据类型和具体变量的关系,是进行程序设计的基础。
1、类的定义
类定义了事物的属性和它可以完成的动作(它的行为)。类包括描述其属性的数据和对这些数据进行操作的函数。定义方法如下:
class 类名 { public 数据成员; 成员函数; private 数据成员; 成员函数; protected 数据成员; 成员函数; };
例如:下面程序定义了一个时间类。
class CTime { private: int hour, minute, second; public: void print() { cout << hour << ":" << minute << ":" << second << endl; } void SetTime(int h, int m, int s) { hour = h; minute = m; second = s; } };
该时间类包括三个私有数据成员,分别表示时、分、秒,两个公有成员函数用域设置时间、输出时间。
关于类的定义需要注意以下几点:
- class是定义类的关键字,class后的类名是用户根据程序需要自己定义的,只要复合标识符命名规则就可以。按照通常做法,一般以大写的class字头C开头,C后首字母大写。类名后的{}括起来的部分为类体,需要注意的是类体后面的 ”;"不能省略。
- 类体内的数据成员。数据成员一般是一系列变量的声明,但要注意的是不能在声明变量时就初始化。因为类只是相当于数据类型,不是具体变量,所以无法赋值。
- 类的数据成员和成员函数前的三个关键字public、private和protect表示三种不同的访问权限:
- public(公有的):公有的数据成员和成员函数可以被程序中任何函数或语句调用。
- protected(保护的):保护成员不能被类外的函数或语句调用,只有该类的成员函数才能存取保护成员。但是如果该类派生了子类,则子类也可以存取保护成员。
- private(私有的):私有成员就只能被类中函数访问,类外的函数或语句无法存取。
- 如果定义类时,数据成员或成员函数前没有写任何关键字,则默认的访问权限是private。由于私类成员在类外不可见,很好的体现了类的封装性,公有成员则是类与外部程序的接口。
- 在类体内,三个表示访问权限的关键字不必同时出现,即使同时出现,先后顺序也可以随意放置,并且同意关键字可以出现多次。
- 类的定义域struct定义结构体类型时的格式相同,只是结构体只有数据成员,没有成员函数。结构体成员前也可以用public、private和protected限定访问权限,但一般情况下都没有写,采用默认方式(public)。所以结构体也可以看作是类的一种。
2、对象的定义
类相当于一种数据类型,可以用来定义具体变量,即进行类的实例化,创建对象。具体格式如下:
(1)先定义类,再定义对象,格式为: <类名> <对象名表> (2)定义类的同时定义对象,格式为: class <类名> { 类的成员 }<对象列表>;
定义对象时,需要注意以下几点:
- 对象名表可以是一个对象名,也可以是多个对象名,各个对象名之间用逗号隔开即可。例如:
CTime t1,t2;
- 对象不仅可以是一般对象,还可以是数组、指针或引用名。例如
CTime t[24],pt,&rt=t1;(t1是已经定义过的同类对象)
- 对象不仅可以是一般对象,还可以省略类名,即用无名类直接定义对象,只是没有类名,在后续程序中能再继续使用。
2、类的成员函数
再类体内,成员函数表示的是类的行为,是类与外部程序的接口。成员函数的定义可以放在类体内,也可以放在类体外。当成员函数放在类体内是,即使没有关键字inline修饰,该函数也为内联函数。如果成员函数的定义放在类体外,在类体内需要加函数声明,在类体外定义函数时,函数名前要加强类名和作用域运算符::。如时间类可以改为如下格式:
class CTime { private: int hour, minute, second; public: void print() { cout << hour << ":" << minute << ":" << second << endl; } void SetTime(int h, int m, int s);//类体内的函数声明 }; void CTime::SetTime(int h, int m, int s)//类体外的函数定义即函数实现 { hour = h; minute = m; second = s; }
此时,成员函数不是内联函数,乳沟要将定义在类体外的成员函数设置为内联函数,必须用关键字inline进行显示声明,即在返回值类型前加上inline。
3、对象的使用以及对成员的访问
用类定义了对象后,对象就具有与类相同的属性和行为,类有哪些成员,对象就有哪些成员,既包括数据成员也包括成员函数。对象成员的表示方法为:
<对象名>.<数据成员> <对象名>.<成员函数>(<参数表>)
例如,用时间类定义对象t1,并表示t1的所有成员。
CTime t1; t1.hour,t1.minute,t1.second,t1.SetTime(8,0,0),t1.print()
如果对象是对象指针,则将成员运算符.换成->,即:
<对象指针名>-><数据成员> <对象指针名>-><成员函数>(<参数表>)
例如:
CTime *pt=t1; pt->hour,pt->minute,pt->second,pt->SetTime(8,0,0),pt->print()
示例:编程,用时间类的对象输出时间
方法1:使用一般对象
#include "stdafx.h" #include<iostream> using namespace std; class CTime { private: int hour, minute, second; public: void print() { cout << hour << ":" << minute << ":" << second << endl; } void SetTime(int h, int m, int s);//类体内的函数声明 }; void CTime::SetTime(int h, int m, int s)//类体外的函数定义即函数实现 { hour = h; minute = m; second = s; } int main() { CTime t1; t1.SetTime(11, 0, 0); t1.print(); return 0; }
运行结果如下:
方法2:使用对象指针
#include "stdafx.h" #include<iostream> using namespace std; class CTime { private: int hour, minute, second; public: void print() { cout << hour << ":" << minute << ":" << second << endl; } void SetTime(int h, int m, int s);//类体内的函数声明 }; void CTime::SetTime(int h, int m, int s)//类体外的函数定义即函数实现 { hour = h; minute = m; second = s; } int main() { CTime t1,* pt = &t1; //pt为对象指针 pt->SetTime(11, 0, 0); pt->print(); return 0; }
方法3:使用对象引用
int main() { CTime t1, &rt=t1; //rt为对象引用 rt.SetTime(11, 0, 0); rt.print(); return 0; }
4、构造函数与析构函数
在C++中,构造函数和析构函数是类的两个特殊的成员函数,特殊之处在于,构造函数和析构函数都与类同名,只是析构函数名要在类名前加上符号~。两个函数都是公有的,由系统自动调用。在创建对象时系统会自动调用相应的构造函数进行对象的初始化;当一个对象的生存期即将结束时会调用析构函数做释放内存等清理工作。
1、构造函数
构造函数作为类的成员函数,是在类体内定义的,函数名与类名相同,与一般函数不同,他不能指定任何返回类型(包括void)。而且C++允许构造函数的重载。作为类的成员函数,构造函数可以直接访问类的所有数据成员,根据构造函数参数的具体情况,将构造函数分为以下几种:
- 默认构造函数(不带参数)
在类定义时,如果没有定义构造函数,系统会自动生成一个默认构造函数,而且不带任何参数,函数体是空的,形式为:
<类名>(){}
由于默认构造函数不带参数,为对象初始化时不被指定任何具体值。此时系统会按照对象的存储类型不同区别对待,如果对象是auto存储类型,则数据成员的额初始值是无效的,如果是extern或static存储类型,则数据成员初始值为其默认值(0或空)。上例中都没有给出构造函数的定义,但实际上都采用了默认构造函数,具体构造函数形式为:
CTime(){}
- 带参数的构造函数
一般的,构造函数都带有参数,创建构造对象时给出实参,系统会根据实参个数、类型调用相应的构造函数为对象进行初始化。其一般形式为:
<类型>(函数名1 参数1,类型名2 参数2,...) { 函数体 }