if(n>2)
return_chengNum(n-1);
else
{
returncountNum;
}
}
源码下载:
二结构和类
1.自定义数据类型
C++中的结构:
结构是使用关键字struct定义的用户定义类型。
结构起源于C语言,C++继承并扩展了结构。
C++中的结构在功能上可以由类代替,因为任何使用结构能够做到的事情都可以使用类做到。
但是因为Windows是在广泛应用C++之前用C语言编写的,所以结构遍布在Windows编程的各个方面。
今天,结构仍然被广泛使用,因此我们确实需要了解结构。
2.结构的概念
考虑一下要描述像一本书这样简单的事物需要多少信息。
我们首先可能想到书名,作者,出版社,出版日期,页数,定价,主题或分类以及ISBN号,还可能不太困难地就想到一些其他信息。
我们可以指定相互独立的变量来容纳描述一本书所需的每项信息,但更希望能够使用一种数据类型来包含所有这些信息。
这正是结构能为我们做的事情。
3.定义结构
假设只需要在书的定义中包括书名,作者,出版社和出版年份。
structBook
{
chartitle[80];
charauthor[80];
charpublisher[80];
intyear;
};
这里的代码没有定义任何变量,但实际上创建了一种新的类型,该类型的名称是BOOK。
关键字struct将BOOK定义成结构,构成本类型对象的元素是大括号内定义的。
结构体内的元素可以是除所定义的结构类型以外的任何类型。
例如,BOOK的结构定义中不能包括类型为BOOK的元素。
我们可以认为这是一种局限性,但BOOK定义中可以包括BOOK类型变量的指针。
创建其他类型变量的方式来创建BOOK类型的变量:
BOOKnovbel;//声明一个BOOK类型的变量novbel.
4.初始化结构
第一种将数据存入结构成员的方法,是在声明语句中为结构体成员定义初始化。
Booknovel
{
“PanelessPrograming”,
"I.c.Fingers",
"GutterPress",
1981
};
这些初始化值位于初始化列表内,相互之间以逗号分开,这种方式与为数组成员定义初始值的方式完全相同。
5.访问结构的成员
为了访问结构各个成员,可以使用成员选择操作符”.”,有时称之为成员访问操作符。
如果想修改Novel结构的Year成员可以这样写:
novel.year=1988;
1
6.RECT结构在windows程序中,矩形用的很多。
因此,包含在windows.h的windef.h头文件中有一个预定义的RECT结构,,其定义本质是
structRECT
{
LONGleft;
LONGtop;
LONGright;
LONGbottom;
};
MFC(微软基础类库(英语:
MicrosoftFoundationClasses,简称MFC)是一个微软公司提供的类库(classlibraries),以C++类的形式封装了WindowsAPI,并且包含一个应用程序框架,以减少应用程序开发人员的工作量。
其中包含的类包含大量Windows句柄封装类和很多Windows的内建控件和组件的封装类。
)MFC也定义了等价于RECT结构的CCRect类。
当我们理解类之后,将优先使用CRect大类而非RECT结构。
CRect类提供了很多处理矩形的函数,在使用MFC编写Windows程序时将大量使用这些函数。
7.使用指针处理结构
可以创建指向结构类型对象的指针。
windows.h中声明的许多处理RECT对象的函数都要求实参是指向RECT的指针,因为这样可以避免给函数传递RECT实参时复制整个结构的系统开销。
RECT*pRect{};//声明一个指针指向RECT
1
假设已经定义了一个RECT对象&aRect,那么可以使用通常的方式将aRect变量的地址赋予pRect指针:
pRect=&aRect;
1
struct不能包含与被定义结构类型相同的成员,但可以包含指向struct的指针,其中包括指向相同类型struct的指针。
structListElement
{
RECTaRect;
ListElement*pNext;
}
8.通过指针访问结构成员
RECTaRect{0,0,100,100};
RECT*pRect{&aRect};
1
2
第一条语句声明并定义了一个RECT类型的对象aRect,将第一对成员初始化为{0,0},将第二对成员初始化为{100,100}。
第二条语句将pRect声明为指向RECT类型的指针,并将其初始化为aRect的地址。
现在,可以用下面的语句,通过指针访问aRect的成员:
(*pRect).top+=10;
1
这里使用的通过指针访问struct成员的方法看起来相当笨拙。
这种操作在C++中出现得相当频繁,因此C++提供了一个特殊操作符,间接成员选择操作符(->)。
pRect->top+=10;
1
该语句更清楚地表示自己的用途。
在本书中经常会看到该操作符。
9.数据类型,对象,类和实例
基本类型的变量不能充分模拟现实世界中的对象或虚拟的对象。
例如,很难用int模拟一个箱子,但可以使用struct成员为这样的对象定义一组特性。
如下所示,可以定义length,width和height这3个变量来表示箱子的尺寸,并将它们作为Box结构的成员捆绑到一起:
structBox
{
doublelength;
doublewidth;
doubleheight;
};
有了名为Box的新数据类型的定义之后,就可以像定义基本类型变量那样定义该类型的变量。
在程序中,可以创建,处理和销毁任意数量的Box对象。
这意味着可以使用struct来模拟对象,并围绕对象编写程序。
因此,这就是面向对象编程,对吗?
对,但不完全对。
面向对象编程(OOP)基于与对象类型相关的3个基本概念,即封装,多态性和继承性,而我们目前所看到的不完全与之吻合。
在C++中,struct的概念远远超出了C语言中原来的struct概念,它现在合并了类的面向对象思想。
类的思想–可以创建数据类型并像使用已有类型那样使用,对C++而言非常重要,因此该语言引入了一个新关键字class来描述类这一概念。
在C++中,除了成员的访问控制以外,关键字struct和class几乎是等同的。
保留关键字struct是为了向后兼容C语言,但使用struct能实现的一切都可以用类来实现,而且类可以比struct实现更多的功能。
定义表示箱子的类:
classCBox
{
public:
doublem_length;
doublem_width;
doublem_height;
};
与定义Box结构的情况类似,将CBox定义成类时,实质上是在定义新的数据类型。
仅有的区别是使用了关键字class代替struct,还在类成员的定义前面使用了后跟冒号的关键字public。
作为类组成部分被定义的变量称为类的数据成员,因为他们是存储数据的变量。
public关键字提供了区别结构和类之间的线索。
以该关键字定义的类成员通常是可以访问的,其访问方式与访问结构成员相同。
默认情况下,类成员一般是不可访问的,而是私有的(private)。
为了使类成员可访问,就必须在他们的定义前面使用关键字public。
结构成员默认是共有的。
类成员默认情况下之所以是私有的,一般是因为类对象应该是自包含实体,这样的数据使对象应该被封装起来,并且只能在受控制的情形下修改。
公共的数据成员是非常少见的例外情况。
MFC采用了在所有类名称以C作为前缀的约定,因此我们也要养成这样的习惯。
MFC还给类的数据成员添加m_前缀,以便将他们与其他变量区别开来。
可以像下面这样,声明一个表示CBox类类型的实例bigBox
CBoxbigBox;
1
10.类的起源:
类的概念是以为英国人为使普通人保持心情愉快而发明的,它源于”知道自己在社会中的地位和作用的人们,生活将比那些对此茫然无知的人更感到安全和舒适”这一理论。
著名的C++发明者丹麦人BjarneStroustrup在剑桥大学期间学到了深奥的类概念,并非常成功地将之应用到他的新语言中。
类通常都有非常精确的任务和一组可以执行的动作,从这一点来讲,C++中的类与英语原意相同。
但是,C++中的类与英语原意是有区别的,因为他们很大程度上专注于实现工作类的价值。
实际上,在某些方面他们甚至与英语原意相反,因为C++中的工作类往往位于那些完全不做任何事情的类背后。
11.类的操作
在c++中,可以创建新的数据类型–类,来表示任何希望表示的对象。
类(以及结构)不仅限于容纳数据,还可以定义成员函数,甚至可定义在类对象之间使用标准C++运算符执行操作。
还可以在CBox类中实现使box相加,相减乃至相乘的操作。
事实上,几乎任何在box上下问中有实际意义的操作都可以实现。
这里谈论的是令人难以置信的强大技术,它使我们采用的编程方法产生了重大变化。
我们不在根据本质上与计算机相关的数据类型(整数,浮点数等)分解问题,然后编写程序,而是根据与问题相关的数据类型(换一种说法就是类)进行编程。
12.类的相关术语
类是用户定义的数据类型。
面向对象编程(OOP)是一种编程风格,它基于将自己的数据类型定义成类的思想,这些数据类型专用于打算解决的问题的问题域。
声明类的对象有时称作实例化,因为这是在创建类的实例。
类的实例称为对象,
对象在定义中隐式地包含数据和操作数据的函数,这种思想称为封装。
13.理解类
类是用户定义的数据类型的说明,其包含的数据元素可以是基本类型或其他用户定义类型的变量。
类的数据元素是单数据元素,数组,指针,几乎任何种类的指针数组或其他类的对象,因此在类类型可以包括的数据方面有非常大的灵活性。
类还包含通过访问类内的数据元素来处理本类对象的函数。
因此,类组合了构成对象的元素数据的定义和处理奔雷对象中数据的方法。
类中的数据和函数称为类的成员。
奇怪的是类的数据项称为数据成员,函数的类成员称为函数成员或成员函数。
类的成员函数有时也称作方法。
定义类时,就是在定义某种数据类型的蓝图。
我们没有实际定义任何数据,但确实定义了类名的意义--即类对象将由那些数据组成,对这样的对象可以执行什么操作。
如果要编写基本类型double的说明,则情况完全相同。
但我们编写的不是double类型的实际变量,而是这种变量的构成和操作的定义。
为了创建基本数据类型的变量,需要使用声明语句。
创建变量的情形完全相同。
14.定义类:
定义表示箱子的类:
classCBox
{
public:
doublem_length;
doublem_width;
doublem_height;
};
类名跟在class关键字后面,3个数据成员在大括号内定义的。
数据成员的定义使用我们已经很熟悉的声明语句,整个类定义以分号结束。
所有类成员的名称都是该类的局部变量。
因此,可以在程序中的其他地方使用相同的名称,包括其他类定义。
类的访问控制:
public关键字决定着后面那些类成员的访问属性。
将数据成员指定为public,意味着在包含这些成员的类对象的作用于内的任何位置都可以访问它们。
还可以将类成员指定为private或protected,此时这些成员不能在类的外部访问。
事实上,如果完全省略访问说明,则成员的默认访问属性是private(这是类和结构之间的唯一区别--结构的默认访问说明符是public)。
15.声明类的对象
声明类的对象的方法与声明基本类型对象的方法完全相同。
因此,可以用下面的语句声明类类型CBox的对象:
CBoxBox1;
CBoxbox2;
1
2
box1和box2这两个对象都拥有各自的数据成员。
16.访问类的数据成员
可以使用访问结构成员时用过的直接成员选择操作符来引用类对象的数据成员。
17.对象成员的初始化
因为CBox对象的数据成员是public,所以在创建对象时,可以在初始化列表中指定他们的值:
CBoxbox1{2.5,3.5,4.5};
1
box1的成员按顺序获取列表的值,所以m_Length是2.5,m_Height是4.5。
如果在列表中提供的值少于数据成员的个数,未获取值的成员就设置为0。
CBoxbox2{2.5,3.5};
1
也可以提示一个空列表,把所有成员都初始化为0:
CBoxbox3{};
1
18.初始化类成员
classCBox
{
public:
doublem_length{1.0};
doublem_width{1.0};
doublem_height{1.0};
};
初始化类成员的语法与普通变量相同,也是使用初始化列表。
初始化应用于所创建的任何CBox对象的成员,除非成员的值通过其他方式设置。
19.类的成员函数是其定义或原型在类定义内部的函数