文章目录
前言
之前的内容是基于过程的程序设计,现在开始基于对象的程序设计,最后才是面向对象的程序设计。
一、入门基本概念
1.基于过程的程序设计、基于对象的程序设计、面向对象的程序设计的区别
①基于过程的程序设计
②面向对象的程序设计:基于对象的程序设计和面向对象的程序设计
看到上面的分类,大家一定觉得很好奇,尤其是第②点,现在我从根上细细讲解,首先c++是由c发展而来,c++保留了c绝大部分的功能和运行机制,所以c++不是一个纯粹的面向对象的语言,而是一种基于过程和面向对象的混合型语言。
从程序结构上来看:
基于过程的程序中,函数是构成程序的基本部分,程序面对的是一个个函数,除了主函数只能被操作系统调用外,各个函数可以相互调用,程序的基本构成单位是函数,程序的主要工作是针对过程设计函数;
面向对象的程序中,程序面对的是一个个类和对象,除主函数外,其他函数都是出现在类中,只有通过类才能调用类中的函数,程序的基本构成单位是类和对象,程序的主要工作是设计类,定义和使用类对象。
2.类、对象、封装、抽象、继承、多态
①类、对象:
现实中任何一个对象都有静态特征(属性attribute)和动态特征(行为behavior)两个要素,各个对象之间通过一定的渠道相互联系,要是某个对象实现某种行为,应当向他发送消息。编程中就是采用这种思路,C++中每个对象都有数据(属性)和函数或者叫方法(行为),调用对象中的函数就是向该对象传送一个消息,要求该对象执行指定的函数以实现某一行为。
②封装:1)将数据和操作代码封装在一个对象中;2)将对象中的某些部分对外隐蔽,隐藏内部细节,只留少数的接口,以便与外界联系,接收外部的消息,对象中的函数名就是对象的对外接口,外界可以通过函数名调用这些函数来实现某些行为(功能)。
③抽象:抽象的作用是表示同一类事物的本质,如整形数据是对所有整数的抽象,再者“美国人”类是对所有美国人的抽象,“中国人”类是对所有中国人的抽象。
④继承:在设计类的时候,沿用其他类的一些属性和方法(包括自己设计的类、别人设计的类或者是系统类库中的类),涉及到父类(基类)和子类(派生类)的叫法,同时C++提供的继承机制,可以很方便的利用一个已有的类建立一个新类,可以重用已有软件中一部分甚至大部分的代码,减少编程工作量,这就是软软件中的概念“软件重用”。
⑤多态(性):C++中指的是由继承而产生的不同的派生类,其对象对同一个消息作出不同的响应。
3.类和对象的作用
①基于过程的软件开发:程序 = 算法 + 数据结构
②基于对象和面向对象的程序: 程序 = n个对象 + 消息
4.面向对象的软件开发
软件的开发涉及到很多的工作和内容,一个大型的软件更是如此,他们严格按照以下5个阶段进行:
①面向对象的分析(OOA)
②面向对象的设计(OOD)
③面向对象的编程(OOP)
④面向对象的测试(OOT)
⑤面向对象的维护(OOSM)
但是如果是一个简单的问题,可以不必按照以上5个阶段,灵活运用。
二、类和结构体的前世今生
1.两者的异同
C++中的类类型是有结构体发展而来的,两者是一样的,只是c++中结构体中也可以包含函数。只是在默认的情况下两者数据成员和成员函数的成员访问限定符不一样。
2.类类型和对象的定义
类类型是一种自定义的数据类型,和结构体一样,只能被声明,他的对象才叫被定义。
①类类型定义:参考结构体
class 类名
{
private:
私有的数据成员和成员函数;
public:
公有的数据成员和成员函数;
}
//类的声明
class Student
//类体
{
//成员表
private://成员访问限定符
char name[10];//数据成员
char sex;
public:
int num;
void display()//成员函数
{
cout << num << endl;
}
};
int main(int argc, char* argv[])
{
//对象的定义,分配空间
Student st;
st.num = 20;
st.display();
return 0;
}
②对象的定义:参考结构体有3种
1)先声明结构体,后定义对象(常用做法)
2)声明的同时定义对象
3)声明不出现类名直接定义对象
三、类的成员函数、对象成员的引用、公共接口和私有实现分离、类的声明和成员函数的分离
1.类的成员函数
类中成员函数是类体中很重要的部分,没有它那就等同于c语言中的结构体。
①类的成员函数可以在类体中定义,也可以在类体外定义(类体中声明,类体外定义时加上作用域限定符**::**,类的定义还要放在成员函数之前,不然编译报错,类比不同函数的声明和定义),而且后面讲分离的时候还要讲到放在不同的文件中。
//类的声明
class Student
//类体
{
//成员表
private://成员访问限定符
char name[10];//数据成员
char sex;
public:
int num;
void display();//成员函数声明
};
//成员函数定义
void Student::display()
{
cout << num << endl;
}
int main(int argc, char* argv[])
{
//对象的定义,分配空间
Student st;
st.num = 20;
st.display();
return 0;
}
②成员函数的存储方式(或者叫内存模型),采用的第二种,具体的是使用了一种叫this的指针,同时保存保存的位置也有讲究,具体的后续学到再添加。
2.对象成员的引用
程序中经常需要访问对象中的成员(数据成员和成员函数),有3种方法可以使用
①通过对象名和成员运算符(“.”)访问对象中的成员;
②通过指向对象的指针访问对象中的成员;
③通过对象的引用访问对象中的成员(参考之前的文章中引用的讲解)。
3.公共接口和私有实现分离
在面向对象的程序设计中,在声明类时,一般都是把所有的数据指定为私有的,使它们和外界隔离,而把需要外界调用的成员函数指定为公有的(私有的成员函数称为工具函数),在类外不能直接访问数据,但是可以通过公有的成员函数引用甚至修改私有的数据成员。
同时一些软件开发公司只提供类的头文件(接口)和公有成员函数(实现)的目标文件,用户只需要#include头文件,在链接的时候自然就和公有成员函数的目标文件进行链接。这就是类的公用接口和私有实现相分离,这是所有软件设计中一个基本原则。
可以看的出来,只要类的接口没有改变,对私有实现的修改不会引起程序其他部分的修改。
4.类的声明和成员函数的分离
和上述3类似,一般一个c++程序是由3个部分组成的:1)类的声明头文件(.h);2)类实现文件,包括成员函数定义等(.cpp);3)类的使用文件(.cpp)。
还有一点就是实际中,不是将一个类声明做成头文件,而是将若干个常用功能相近的类声明集中在一起,形成各种类库(类的声明头文件和已经编译的成员函数的目标文件),用户只需将类库安装到c++编译系统的子目录下,然后在#include即可。可以保护软件开发商的版权,也方便升级。
所以我们在以后的编程中也要采用这种思想。规范编码。通过以上我们看出了类的封装性和信息的隐蔽,同时类中不能都定义成private,否则这个类就没有任何的使用价值,至少要留1个公有接口供外部调用。
四、面向对象的程序设计的几个名词
stud.display();
以上涉及到3个名字:
对象:stud是对象;
方法:指对数据的操作,一种方法对应一种操作。
消息:是一个命令,有程序语句来实现,调用对象的方法(stud.display();)就是发一个发给对象的消息,要求对象执行一个操作。
五、简单的程序设计入门
例子1:用类来实现时间的输入和输出,代码如下(示例):
//用类来实现时间的输入和输出
////方法1
////类的声明
//class Time
////类体
//{
//public:
// int hour;
// int minute;
// int sec;
//};
//
//int main(int argc, char* argv[])
//{
// //对象的定义,分配空间
// Time t1;
// cin >> t1.hour;
// cin >> t1.minute;
// cin >> t1.sec;
//
// cout << t1.hour << ":" << t1.minute << ":" << t1.sec << endl;
//
// return 0;
//}
//方法2
//类的声明
class Time
//类体
{
public:
void set_time();
void show_time();
private:
int hour;
int minute;
int sec;
};
void Time::set_time()
{
cin >> hour;
cin >> minute;
cin >> sec;
}
void Time::show_time()
{
cout << hour << ":" << minute << ":" << sec << endl;
}
int main(int argc, char* argv[])
{
//对象的定义,分配空间
Time t1;
t1.set_time();
t1.show_time();
return 0;
}
例子2:找出一个整形数组中的元素最大值,要求1)将类的定义放在头文件arraymax.h中;2)将成员函数定义放在源文件arraymax.cpp中;3)主函数放在源文件file1.cpp中,代码如下(示例):
arraymax.h
#ifndef __ARRAY_H__
#define __ARRAY_H__
class Array_max
{
public:
void set_value();
void max_value();
void show_value();
private:
int arrary[10];
int max;
};
#endif
arraymax.cpp
#include "stdafx.h"
#include "arraymax.h"
#include <iostream>
using namespace std;
void Array_max::set_value()
{
int i;
for(i = 0; i < 10; i++)
{
cin >> arrary[i];
}
}
void Array_max::max_value()
{
int i;
max = arrary[0];
for(i = 1; i < 10; i++)
{
if(max < arrary[i])
{
max = arrary[i];
}
}
}
void Array_max::show_value()
{
cout << "max = " << max << endl;
}
file1.h
#include "stdafx.h"
#include "arraymax.h"
int main(int argc, char* argv[])
{
//对象的定义,分配空间
Array_max t1;
t1.set_value();
t1.max_value();
t1.show_value();
return 0;
}
结论:可以看出,在主函数中做的事情:1)定义对象;2)向各对象发出消息,即调用有关对象的成员函数,去完成相应的操作。主函数很简单,语句很少,在大多数的情况下甚至不出现控制结构(判断结构和循环结构),而在成员函数中常会使用控制结构,在面向对象的程序设计中,最关键的工作是设计类,所有的数据和对数据的操作都体现在类中,只要把类设计好,编写程序的工作就显得很简单。