2019-04-04 C++学习笔记之类和对象(上)
参考资料:《21天学通C++》、《C++语言程序设计(第4版)》
面向对象程序设计的基本特点
抽象
面向对象方法中的抽象,是指对具体问题(对象)进行概括,抽出一类对象的公共性质并加以描述的过程。一般来讲,对一个问题的抽象应该包括两个方面:数据抽象和行为抽象。
封装
封装是指将抽象得到的数据和行为(或功能)相结合,形成一个有机的整体,也就是将数据与操作数据的函数代码进行有机的结合,形成“类”,其中的数据和函数都是类的成员。
封装的目的是增强数据的安全性和简化程序的编写工作。
继承
C++提供了类的继承机制,允许在保持原有类特性的基础上,进行更具体、更详细的说明。
多态
多态一般是指一段程序能够处理多种类型对象的能力。在C++中,这种多态性可以通过强制多态、重载多态、类型参数化多态、包含多态四种形式来实现。
类
什么是类
类是指具有相似内部状态和行为的实体的集合。
对于一个具体的类,其包含许多具体的个体,这就是对象。
结构到类
在C++中,结构体除了可以包含变量外,还可以包含函数。
例1 包含成员函数的结构体
#include <iostream>
using namespace std;
struct point { //定义结构体
int x;
int y;
void print() { //定义成员函数
cout << "x = " << x << endl;
cout << "y = " << y << endl;
}
};
void main() {
point pt; //定义结构体变量
pt.x = 0;
pt.y = 1;
pt.print(); //引用成员函数
}
输出:
x = 0
y = 1
注意:调用结构体的成员函数,需要加上后面的(),表示其调用的是成员函数,而不是变量。
例2 结构体到类(有错)
#include <iostream>
using namespace std;
class point { //声明类
int x;
int y;
void print() { //定义成员函数
cout << "x = " << x << endl;
cout << "y = " << y << endl;
}
};
void main() {
point pt;
pt.x = 0;
pt.y = 1;
pt.print(); //调用成员函数
}
该段程序执行后会报错,原因是:结构体在默认情况下,其成员是公有(public)的;类在默认情况下,其成员是私有(private)的。在一个类当中,公有成员是可以在类的外部进行访问的,而私有成员只能在类的内部进行访问。
若要解决以上问题,只需要将类中定义的变量x和y以及定义的成员函数print()都定义为公有的就可以,即在前面加上标识符public。
class point { //声明类
public:
int x;
int y;
void print() { //定义成员函数
cout << "x = " << x << endl;
cout << "y = " << y << endl;
}
};
注意:在书写时,习惯将共有类型放在最前面。
从上述代码可以看出,类与结构体的区别除了使用关键字class和struct不同以外,更重要的是在成员的访问控制方面有所差异。
类的声明
类描述了具有共同特征的一组对象,这组对象的属性和行为相同,只不过具体对象的属性值等有所区别。
C++中类的定义一般分为类的声明部分和类的实现部分。其中类的声明的格式如下:
class Classname {
public:
外部接口
protected:
保护型成员
private:
私有成员
};
其中的参数说明如下:
- class:类说明的关键字
- Classname:用户自定义的C++标识符。注意:类名的风格是:所有类的名字都以大写字母C开头,以表示这是个类的名字,如Cbook,Cstudent等。
- {}:被花括号括起来的部分称为类体。类体主要由一些变量和函数说明构成,分别成为类的数据成员和函数成员,统称为类成员。
注意:类的说明也是以分号结束的。
例3 类的声明
#include <iostream>
using namespace std;
class Cbook { //声明类Cbook
private: //下面的为私有数据
char* m_pczNaame;
int m_nPages;
int m_nEdition;
public: //下面的为公有数据和函数
void GetBookName(char* pName);
int GetTotalPages();
int GetBookEdition();
private: //下面的为私有数据和函数
void SetBookName(char* pName);
void SetTotalPages(int nPages);
void SetBookEdition(int nEdition);
public: //下面的为公有数据和函数
Cbook();
};
void main() {
Cbook op1; //声明对象
cout << "Class define success." << endl;
}
输出:
Class define success.
上述代码声明了一个类Cbook;在main()函数中,使用该类定义了一个对象op1。Cbook类中定义了私有和公有两类成员,其数据成员都为私有,这是出于封装的目的,不希望直接访问数据成员,而是通过所提供的公有函数访问。
类的访问和控制
在C++中,类体被分为以下三类:
- 公有成员
- 私有成员
- 保护成员
上述几个关键字被称为访问说明符,用来控制相应成员在程序中的可访问性。
关于类的三种成员的访问控制,在C++中有一定的访问规则:
- 公有成员在程序的任何位置都可以以正确的方式访问它。
- 私有成员只能被其自身成员所访问,即私有成员的名字只能出现在所属类体、成员函数中,不能出现在其他函数中。
例4 类的访问控制(有错)
#include <iostream>
using namespace std;
class point { //声明类
private:
int x; //定义成员变量
int y;
public:
void print() { //定义成员函数
cout << "x = " << x << endl; //在类中访问
cout << "y = " << y << endl;
}
};
void main() {
point pt; //声明对象
pt.x = 0; //错误:在外部访问类的私有成员
pt.y = 1;
pt.print(); //访问类的公有成员
}
注意:类体中可以出现多个说明符,每个说明符也可以出现多次,不同说明符的出现次序没有限制。当从类体开始到某些类成员前没有访问说明符,或类体中根本没有访问说明符时,这些成员被默认为是私有成员。
类的定义
若要给出这一类对象的具体行为,还应该对类的成员函数进行定义,即类的实现。成员函数的定义有时也被称为类体的定义或类的定义。
一般来说,成员函数的定义格式如下:
ReturnType Classname :: FunctionName(ArgumentList) {
函数体
}
其中参数说明如下:
- ReturnType:表示该成员函数的返回类型,可以是基本数据类型和构造数据类型。
- ClassName:表示类的名称。如果在类的内部定义成员函数,则类的名称可以省略。
- :::域运算符,用来指定后面的函数是属于哪一个类。如果在类的内部定义函数,该运算符和类名可以一起省略。
- FunctionName:函数名,可以是任一标识符。
- ArgumentList:参数列表。
成员函数与一般函数定义不同的是多了类名和域运算符。
注意:在函数中调用的属性和其他成员函数为当前对象所具有的属性和成员函数。
例5 定义类的成员函数的实现
#include <iostream>
using namespace std;
class Cbook { //声明类Cbook
private: //下面的为私有数据
char* m_pczName;
int m_nPages;
int m_nEdition;
public: //下面的为公有数据和函数
void GetBookName(char* pName);
int GetTotalPages();
int GetBookEdition();
private: //下面的为私有数据和函数
void SetBookName(char* pName);
void SetTotalPages(int nPages);
void SetBookEdition(int nEdition);
public: //下面的为公有数据和函数
Cbook();
};
void Cbook::GetBookName(char* pName) { //定义成员函数
strcpy(pName, m_pczName);
}
int Cbook::GetBookEdition() { //定义成员函数
return m_nEdition;
}
void Cbook::SetBookName(char* pName) { //定义成员函数
if (m_pczName != 0)
delete[] m_pczName;
m_pczName = new char[strlen(pName + 1)];
strcpy(m_pczName, pName);
}
void Cbook::SetTotalPages(int nPages) { //定义成员函数
m_nPages = nPages;
}
void Cbook::SetBookEdition(int nEdition) { //定义成员函数
m_nEdition = nEdition;
}
void main() {
Cbook op1; //声明该类的对象
cout << "Class define success." << endl;
}
此外,类的说明通常放置在一个以.h为扩展名的文件中,称为头文件,其中定义了类的接口,因此可以同其他类的说明同放于一个文件。
如果类的说明的程序行数较多,那么应该将其放在一个独立文件中,文件名应为类名去掉前面的字母C,如Cbook类的说明可以放在头文件book.h中,将类体的定义放在一个以.cpp为扩展名的文件中,这称为类的实现文件。在这个文件的开始部分应该用文件包含指令将类的说明文件包含进来。