数据结构 线性表基础 面向对象部分基础篇(基于c++)

类和对象的特性

1 简介:

       c++是一种基于过程和面向对象的混合型语言。我们一开始接触的大多是基于过程的编程,比如编程解决一道小学生的计算题。

       *基于过程:每个独立存在于程序中的函数,是构成程序的基本部分。各个函数可以任意相互调用。(适用于规模较小的程序)

       *面向对象:构成程序的基本部分变成了类,程序面对的是一个个的类和对象。(适用于规模较大的程序)

       从基于过程的编程转向面向对象的编程。程序员的工作就从设计多个函数(或单一个主函数)解决问题,变成了设计、定义和使用类来解决问题。

       特点(四个):

       抽象、封装、继承、多态性

       对象:

       既然是面向对象,首先就要明白对象是什么。现实世界中,任何事物都能被看作一个对象。为了方便描述和运用对象,我们使每个对象都有两个要素:属性(静态特征、程序中的数据)和行为(动态行为、程序中的函数)。而事实上对象也正是由一组属性和一组行为组成的。比如:英雄联盟这个游戏就可看做一个对象,它的属性有:游戏、占用的内存有近10G等,它的行为有,(当我们需要时)运行游戏。要使某一个对象实现某一种行为,应当向它传送给相应的信息。对象能根据外界给的信息进行相应操作,而”我们需要“就是它接收到的一个信息。

       封装与信息隐蔽

       可以对一个对象进行封装处理,把它的一部分属性和功能对外界屏蔽,也就是说从外界是看不到的,是不可知的。把对象的内部实现和外部行为分隔开来。有具体以下两层含义:

       1. 将有关数据和操作代码封装在一个对象中,形成一个基本的单位。各个对象之间相对独立互不干扰。

       2. 将对象中某些部分对外隐蔽,即屏蔽其内部细节,只留下少量细节,以便和外部联系,接受外部的消息。(信息屏蔽)利于数据安全,防止奇奇怪怪的人了解和修改数据。

       抽象——伟大的思想

       抽象将事物层次化,层次越高的抽象的越厉害。底层的部分细节得以忽略,只向上层提供有用的东西。类就是对象的上层(抽象),而对象是类的具体实现。类代表了一批对象的共性和特点。

       在c++中是要先去声明一个类类型,然后用它去定义若干个对象。类是抽象不占用内存,而对象是具体的占用储存空间。

       继承与重用:

       父类(基类)和子类(派生类)。将一个现有的类(基础)“继承下来”增增改改变成一个新的类(发展)。软件重用,重用已有软件中的一部分,来减少自己的工作量。

       多态性:

       有继承而产生的不同派生类,其对象对同一消息会做出不同的响应。多态性是面向对象程序设计的一个重要基础,能增加程序的灵活性。

       设计思路:

       *把数据和有关的操作封装成一个对象(一小部分,一小部分来考虑程序的设计,每次只用考虑当前设计这部分而非整个过程)。

       1. 设计各种所需的类和对象,即决定把哪些数据和操作封装在一起。

       2. 考虑怎样向有关对象发送消息,以完成所需的任务。(类似于硬件设计中的先设计各个模块,再进行顶层设计)

       基于过程:程序 = 算法 + 数据结构

       面向对象:对象 = 算法 + 数据结构(两者是相关的)

                         程序 = (对象 + ... +对象)+ 消息

        ps:消息的作用:对对象进行控制。

2 C++代码实现:

       声明类类型:(和声明结构体类似,但多了函数/操作)

class student

{

       int num;

       string name;

       char sex;

       void display ()

       {

              cout<<num<<' ';

              cout<<name<<' ';

              cout<<sex;
       }
};

       封装不能太过分,把数据和成员函数全部封装的类没有丝毫作用。-》一般把数据隐藏起来,而把成员函数作为对外界的接口。

class strudent

{

       private:

       int num;

       string name;

       char sex;

       public:

       void diplay()

       {

              cout<<num<<' ';

              cout<<name<<' ';

              cout<<sex;
       }
}

       (如果不定义是私有private,还是公有public的话默认为私有。除了public和private之外还有一种成员访问限定符protected(受保护的),用protected声明的成员不能被类外访问,但可以被派生类的成员函数访问。)

       (在一个类体中可以包含多个public和private的部分,每个部分的有效范围到出现另一个限定访问符或类体结束为止。)

       定义对象的方法:

       1. 先声明类类型,然后再定义对象。

//在已经声明类student的前提下
class student s1,s2;
//或者
student s1,s2;

       2. 在声明类的同时定义对象

class student
{
    public:
    void display()
        {
            cout<<num<<' '<<sex;
        }
    private:
    int num;
    char sex;
}s1,s2;

3 类的成员函数

       成员函数的性质

       类的成员函数(简称类函数)是函数的一种,它是属于一个类的成员,出现在类体中。并且可以被指定为provate\public\protected.

       在使用类函数时,要注意调用它的权限(能否被调用)以及它的作用域(函数能使用什么范围内的数据和函数)。如:私有成员函数只能被本类中的其他成员函数所调用,而不能被外类调用。成员函数可以访问本类对象中的任何成员(包括私有的和共有的),可以引用在本作用域中有效的数据。

       建议:把需要被外界调用的成员函数指定为public,它们是类对外的接口。而把支持其他函数操作的工具函数指定为private与,用户不可调用它们。

       类的成员函数是类体中十分重要的部分。

       在类外定义成员函数

       成员函数可以在类体中定义,也可以在类体中只对成员函数进行声明,而在类外进行函数定义。

class student
{
	public:
		void display();
	private:
		int num;
		string name;
		char sex;
};
void student::display()
{
	cout<<num<<" "<<name<<" "<<sex;
}

      注:
      1. 在类体中直接定义函数时,不需要再函数名前加上类名,因为函数属于哪一个类是不言而喻的。

      2. 但成员函数在类外定义时,必须在函数名前加上类名予以限定。“::”是作用限定符(作用域运算符),用它声明函数是属于哪个类的。

      3. 如果作用域运算符::前面没有类名或什么都没有。则表示display不属于任何类,是全局函数。

::diaplay()
display()

      4. 类函数必须先在类体中做出声明,然后在类外定义,也就是说类体的位置应在函数声明之前

      5. 在类体中进行函数的声明,然后在类外进行函数的定义,是一种好习惯。这样不仅减少了类体的长度,使类体清晰便于阅读,而且能使类的接口和类的实现细节分离。

      内置成员函数

      类的成员函数也可以指定为内置函数。

      在类体中定义的成员函数规模一般都比较小,而系统调用函数的过程所花费的时间开销相对是比较大的。调用一个函数的时间开销远远大于小规模函数体中全部语句的执行时间。

      为了减少时间开销,如果在类体中定义的成员函数不包括循环等控制结构,c++系统自动地对他们作为内置函数来处理。

      c++要求对一般的成员函数(类外定义)要用关键字inline来声明,但对类内定义的函数,可以省略inline。因为这些成员函数以被隐含的指定为内置函数。

class student
{
	public:
		inline void display();
	private:
		int num;
		string name;
		char sex;
};
inline void student::display()
{
	cout<<num<<" "<<name<<" "<<sex;
}

       注:

       如果在类外定义inline函数的话则必须将类定义和该成员函数的定义都放在一个头文件中(或者写在同一个源文件中)。但是,这样做不利于类的接口和类的实现分离,不利于信息隐蔽。

       成员函数的存储方式

       用类去定义对象时,系统会为每一个对象分配存储空间。

       由于同一类的不同对象中的数据成员的值一般是不相同的,而不同对象的函数的代码是相同的,不论调用哪一个对象的函数的代码,其实调用的都是相同内容的代码

       c++编译系统使:每个对象所占用的存储空间只是该对象的数据成员所占用的空间,而不包括函数代码所占用的存储空间。在同一个类定义了多个对象时,只用一段空间来存放这个共同的目标代码。在调用各对象的函数时,都去调用这个公共的函数代码。

       可用下面语句来获得该类对象所占用的字节数:

cout<<sizeof(student)<<endl;

       一个对象所占的空间大小只取决于该对象中数据成员所占的空间,而与成员函数无关。

       虽然调用不同对象的成员函数时都是执行同一段函数代码,但是执行的结果一般是不相同的。这是因为不同的对象的的成员函数访问的都是本对象中的数据成员。c++为了实现这个,专门设置了一个this指针,用来指向不同的对象,当调用A对象的数据成员时,this就指向对象A。

       注:

       1. 不论成员函数是在类内定义还是在类外定义,成员函数的代码段的存储方式都是相同的,都不占用对象的存储空间。

       2. 不要将还成员函数的这种存储方式和inline(内置)函数混淆。inline函数同样也不占用对象的存储空间!不论是否用inline声明,成员函数的代码都不占用对象的存储空间。(inline声明的作用是:在调用该函数时,将函数代码的复制插入到函数调用点;而不用inline声明:在调用该函数时,流程转去函数代码段的入口地址,在执行完该函数代码段后,流程返回函数调用点)inline函数值只影响程序的执行效率,而与成员函数是否占用对象的存储空间无关。

        3. 虽然成员函数的代码并不放在对象的存储空间,但是说是“XX对象的成员函数。。。”从逻辑的角度来说并没有问题。因为:虽然成员函数并没有放在对象的存储空间中,但从逻辑的角度,成员函数是和数据封装在一个对象中的,只允许本对象中成员函数的访问同一对象中的私有数据。

4 对象成员的引用

       在程序中我们常常需要访问对象的成员:

       1. 通过对象名和成员运算符访问对象中的成员;

       2. 通过指向对象的指针访问对象中的成员;

       3. 通过对象的引用访问对象中的成员;

       通过对象名和成员访问运算符访问对象中的成员

       对象名.成员名;

       不仅可以在类外引用对象的公用数据函数,也可以调用对象的公用成员函数,但是它们都要指出对象名。

student.num=1001;
student.display();

.      应当注意所访问的成员是public的还是private的。在类外只能访问public的成员。

       在一个类中至少有一个共用的成员函数,作为对外的接口,否则就无法对对象进行任何操作。

       通过指向对象的指针访问对象中的成员

       用指针访问对象中的成语与用指针访问结构体中的成员类似。

class time
{
    public:
        int hour;
        int minute;
};
timt t,*p;
t.hour=11;
p=&t;
cout<<p->hour;

       当p指向对象t时,(*p).hour    p->hour   t.hour三者等价。

       通过对象的引用来访问对象中的成员

       如果为对象定义了一个引用,表示他是一个对象的”别名“,因此完全可以通过访问引用来访问对象中的成员,其方法和通过对象名和成员访问运算符访问对象中的成员相同。

time t1;
time &t2=t1;//t2是t1的引用
cout<<t2.hour;

5 类的封装性和信息隐蔽

       公用接口与私有现实的分离

       c++通过类来实现封装性,把数据和与这些数据有关的操作封装在同一个类中。

       (类的作用是把数据和算法封装在用户声名的抽象数据类型中

       在声明类时,一般都是把所有的数据指定为私有的,是他们与外界隔离。但把需要让外界调用的成员函数指定为公用的。在类外虽然不能直接访问私有数据成员,但可以通过调用公用成员函数来引用甚至修改私有数据成员。

       这样就使类与外界的联系减少到最低限度。共用函数成员是用户使用的公用接口,或者说是类对外的接口。

       在声明了一个类之后,用户的主要工作就是通过调用其公用成员函数来实现类提供的功能。这些功能是在声明类的时候已经确定了的,用户可以使用它们而不应改变它们。用户往往不关心功能实现的细节,而只须知道调用某函数回到得到的结果。接口与现实的分离。

       类功能的实现:通过调用成员函数对数据成员进行操作。

       为了防止用户任意修改公用成员函数,改变对数据进行的操作,往往不让用户看到公用成员函数的源代码,显然更不能修改他,用户只能接触到公用成员函数的目标代码。

       可以看到:被操作的数据是私有的,类的功能的实现细节对用户是隐蔽的,这种实现成为私有实现。

       ”类的公用接口和私有实现的分离“形成了信息隐蔽.

       将接口与实现分离,信息屏蔽是软件工程中一个十分重要的概念.它有许多好处:

       1. 如果想修改或扩充类的功能,只需修改类中有关的数据成员和它的有关成员函数,类以外的部分可以不必修改.

       例子1:
       在student类中增加一项数据成员"年龄".

class student
{
	private:
		int num;
		string name;
		int age;//新增的
		char sex;
	public:
	void display()
	{
		cout<<num<<endl;
		cout<<name<<endl;
		cout<<age<<endl;//新增的 
		cout<<sex<<endl;
	}
};

       注:

       虽然类的成员变了,成员函数变了,类的功能也变了,但是类的对外接口没有改变,外界仍然通过共用的display函数来访问类中的数据.程序中其他任何部分无需修改.

       当接口与实现(对数据的操作)分离时,只要类的接口没变,对私有实现的修改不会引起程序其他部分的改变.

       2. 如果在编译时发现类中的数据读写有错,不必检查整个程序,只需检查本类中访问这些数据的少数成员函数.

       类声明和成员函数定义的分离

       在面向对象的程序开发中,往往把类的声明(其中包含成员函数的声明)当在指定的头文件中,用户如果想用该类,只要把相关的头文件包含进来即可,不必在程序中重复书写类的声明.

       类声明头文件是用户使用类库的共用接口.

       包含类的成员函数定义的文件就是类的实现.类的声明和类成员函数的定义是分别放在两个文件中的.(为了信息隐蔽,对类函数的定义一般不放在头文件中)

       实际上一个c++文件是由三个文件组成的:1. 类的声明头文件(后缀为.h);2. 类实现文件(后缀为.cpp),它包括类函数的定义;3. 类的使用文件(后缀为.cpp),即主文件.

       类实现文件只需编译一次即可,把编译一次后形成的目标文件保存起来,以后在需要时把它直接与程序的目标文件相连即可.

       在实际工作中,会把若干个常用的功能相近的类声明集中在一起,形成各种类库.(1. 包括类声明头文件;2 已经编译过的成员函数的定义,即类实现的目标文件)

       面向对象程序设计中的几个名词

       方法:是指对数据的操作;

       消息:就是一个命令;

       想要调用一个对象的方法,就是发给对象一个消息,让他执行一个操作(方法).

       注:1. 类型是抽象的,对象是具体的。定义成员函数时应该指定类型名,因为定义的是该类中的成员函数。而调用成员函数时应指定具体的对象名。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 8
    评论
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值