(二)C++学习 | 类和对象(1)


1. 结构化程序设计

C {\rm C} 语言使用结构化程序设计,在程序设计中满足:程序 = 数据结构 + 算法。结构化程序设计特点是:程序由全局变量以及众多相互调用的函数组成;算法以函数的形式实现,用于对数据结构进行操作。如图为结构化程序设计的程序模式:在这里插入图片描述

图1:结构化程序设计的程序模式

如上图,var是变量、sub表示函数、黑色的线表示函数调用、红色的线表示变量调用。由图可知,在结构化程序设计中,首先是主函数调用各函数;然后各函数又调用其他函数;同时众多函数中可能存在诸多全局变量的调用。则很容易得到结构化程序设计的不足

  • 结构化程序设计中,函数和其操作的数据结构没有直观的联系
  • 随着程序规模的增加,程序逐渐难以理解,很难一下子看出来:某个数据结构由哪些程序在对其操作,某个函数在操作哪些数据结构,任何两个函数之间存在怎样的调用关系;
  • 结构化程序设计中没有“封装”和“隐藏”的概念,也即是要访问某个变量时就可以直接访问。但当该变量的定义的有改变时,就要把所有访问该变量的语句找出来修改,这对于大型程序来说就会增加相当大的工作量,也不利于程序的维护和扩充;
  • 难以查错,当某个数据结构出错时不能立即判断是哪个函数调用导致的;
  • 无重用性,在编写程序时,发现需要增加某项功能,而在现有程序中已经实现了相同和类似的功能。但只能重写相关代码;
  • 在结构化程序设计中,随着程序规模的增大,由于程序大量函数、变量之间的关系错综复杂,要抽取这部分代码,变得十分困难。

总而言之,在结构化的程序设计中,随着程序规模的不断扩大,程序会变得难以理解难以扩充难以查错难以重用。而下部分介绍的面向对象的程序设计方法,能够很好地解决上述问题。


2. 面向对象程序设计

C {\rm C++} 语言使用面向对象程序设计。面向对象程序设计的特点是:将某类客观事物的共同属性归纳出来,形成一个数据结构;将这类事物所能进行的行为也归纳出来,形成一个个函数,这些函数可以用来操作数据结构;然后,通过某种语法格式,将数据结构和操作该数据结构的函数“捆绑”起来,形成一个。最后,面向对象程序设计的四个基本特点是:抽象封装继承多态。后面的介绍会一步步体现出面向对象程序设计的各个特点。如图为面向对象程序设计的程序模式:在这里插入图片描述

图2:面向对象程序设计的程序模式

如上图,在面向对象程序设计中,程序由主函数以及众多的类组成。各类拥有自己的变量和函数,在主函数中通过生成类的对象来调用类的变量和函数。同时类与类之间也存在相互继承。由此得到,在面向对象程序设计中,满足:程序 = 类 + 类 + 类 + … + 类。下面由一个简单的例子说明面向对象程序设计方法:写一个程序,输入矩形的长和宽,输出面积和周长。
首先,用一个类表示矩形就是将矩形这个东西抽象出来。矩形的属性就是长和宽,用两个变量表示,在类中称之为成员变量;矩形的行为就是求面积和求周长,用两个函数表示,在类中称之为成员函数。二者统称为类的成员。下面是 C {\rm C++} 实现代码:`

class CRectangle {
public:
	int w, h;
	int Area() {
		return w * h;
	}
	int Preimeter() {
		return 2 * (w + h);
	}
	void Init(int width, int height) {
		w = width;
		h = height;
	}
};

上面定义了一个矩形类CRectangle,其含有两个成员变量wh分别表示矩形的宽和高;含有三个成员函数Area()Preimeter()Init()分别用于求矩形的面积、周长和给成员变量赋值。下面是类的使用方法,根据键盘输入的矩形宽和高,自动计算器其面积和周长。

int main() {
	int w, h;
	CRectangle r;								// 声明类的对象
	cin >> w >> h;
	r.Init(w, h);								// 通过类的对象调用初始化函数
	cout << r.Area() << endl << r.Preimeter();  // 通过类的对象调用求面积函数和求周长函数
	return 0;
}

3. 使用类的成员

使用类的成员前,首先需要声明类的对象,如上面在main函数中定义的CRectangle类的对象r。使用类的成员即成员变量和成员函数的方式大体分为以下三种:
(1)对象名.成员名

CRectangle r1, r2;	// 声明类的对象r1和r2
r1.w = 5;			// 使用r1对象给w赋值
r2.Init(5, 4);		// 使用r2对象调用初始化函数给w和h赋值

需要注意一点是:Init函数是作用在r2上的,即Init函数执行期间访问的wh属于r2,这和r1w是相互独立的。
(2)指针→成员名

CRectangle r1, r2;
CRectangle* p1 = & r1;	// 定义p1指针指向r1对象
CRectangle* p2 = & r2;	// 定义p2指针指向r2对象
p1->w = 5;				// 使用p1指针给w赋值
p2->Init(5, 4);			// 使用p2指针调用初始化函数给w和h赋值

(3)引用名.成员名

CRectangle r;
CRectangle& rr = r;	// 定义rr为对象r的引用
rr.w = 5;
rr.Init(5, 4);		// 由于rr定义为r的引用,随着rr的值改变,r的值也改变

此外,类的成员函数和类的定义可以分开写,具体如下,首先定义类:

class CRectangle {
public:
	int w, h;
	int Area();
	int Perimeter();
	void Init(int width, int height);
};

然后在类外实现函数,其中CRectangle::*表明函数不是普通函数,而是类CRectangle的成员函数。

int CRectangle::Area() {
	return w * h;
}
int CRectangle::Perimeter() {
	return 2 * (w + h);
}
void CRectangle::Init(int width, int height) {
	w = width;
	h = height;
}

4. 总结

C {\rm C++} 语言的类机制 C {\rm C++} C {\rm C} 根本区别所在。类机制可以使程序员随心所欲地定义自己的数据类型。类编程的过程更符合人的自然思维,因而成为实质性解决问题的方法。由于在面向对象的程序设计中,设计程序的过程就是设计类的过程。所以,只要将每个类的定义清晰化、各类间的调用条理化,就能写出一个漂亮的程序。
最后,引用一段参考中的话概括类:类是一个十分精巧的机制,为了胜任描述数据类型的全方位的能力,还添置了静态数据成员和静态成员函数,使得记录对象们的整体数据不必随单一对象数据而苟合,也不必随单一对象而捆绑操作。类甚至还添加了友元,给予了不同性质的对象之间的亲密无间性。它存在面向对象编程的争议,仿佛编程世界严密性的外在尊严,也强迫着编程内容的内在尊严:不同类型的对象之间也不应有任何情面可言。好在 C {\rm C++} 法无定法,关于性能、效率的细节它从来都没有忽略过。


参考

  1. 北京大学公开课:程序设计与算法(三)C++面向对象程序设计.
  2. 钱能. C++程序设计教程(第二版)[M]. 北京:清华大学出版社,2005.9.


猜你喜欢

转载自blog.csdn.net/Skies_/article/details/105210055