本篇笔记将按照下面的顺序展开:
为了方便叙述,我们首先定义一个Student类,用来记录学生的姓名、班内学号(两位)、考试成绩等信息.
class Student{
private:
string name;
int number;
double mathScores;
double englishScores;
double chineseScores;
double sum;
double avarage;
void sumUp(){sum=mathScores+englishScores+chineseScores;}
void ava(){avarage=sum/3;}
public:
Student();
Student(string name, int number);
void SetMathScores(double score);
void SetEnglishScores(double score);
void SetChineseScores(double score);
void PrintStudent();
~Student();
};
将上述代码存储到工作目录中,命名为student.h.
我们将通过对这个Student类的讲解、完善、功能实现,深入对C++类的理解。
1. 内联函数
我们已经知道,C++允许将简单且重复使用的函数进行内联,只需在函数定义前加入关键词incline,使用得当可以极大提升效率。
C++的类中同样允许内联,事实上,定义在类声明内的函数都会被自动内联,如sumUp()和ava().
如果愿意,也可以手动进行内联,只需要在定义的时候,在前面加上关键词incline即可.
2. 构造函数
构造函数是特殊的成员函数,用于创建并初始化对象。构造函数没有返回值,但是不需要添加关键词void,可以有参数,也可以没有参数(默认构造函数),通过函数重载进行区分。
构造函数有两种使用方法,显式调用和隐式调用。
Student Xiaoming=Student("Xiaoming",12);
Student Xiaolei("Xiaolei",14);
第一种方法是显式调用,第二种方法是隐式调用。
我们在student.h中定义了两种构造函数,一种没有参数,另一种接受两个参数,前者就是默认构造函数。在实际应用中,我们希望创建一个对象的同时进行初始化,对此,我们有两种书写默认构造函数的方法:
一种是在默认构造函数的定义中进行初始化:
Student::Student(){
name="NULL";
number=-1;
mathScores=0;
englishScores=0;
chineseScores=0;
}
而另一种是重新写一个有默认值的“默认构造函数”
Student(string name="NULL", int number=0, double mathScores=0, double englishScores=0, double chineseScores=0);
请不要同时使用两种方法。
另外请注意,在隐式调用默认构造函数的时候,不要使用圆括号,避免人类程序员阅读的时候与返回Student类的函数发生混淆,降低可读性。
3. 析构函数
析构函数也很特别,在类名前加上~,没有void关键词,而且禁止有参数。因为析构函数什么也不做,所以函数定义中可以不写任何内容:
Student::~Student(){}
在后面的学习中,我们会在构造函数和析构函数的定义中加入一些输出,用来深入研究一个对象的生命周期。
4. const成员函数
下面的代码是不能被执行的:
const Student Noah("Noah",42);
Noah.PrintStudent();
因为Noah是const对象,然而PrintStudent()成员函数并没有保证不对其进行修改。需要一种新的语法来保证成员函数不对调用它的对象进行修改:在声明和定义的后面加上关键词const。
void PrintStudent() const;
一般来说,只要不会修改对象,我们都会将成员函数定义为const的,这样使用起来更方便,在阅读、维护和使用的时候也减少了不少麻烦。
常见的const位置有三种:
const Student& Max(const Student B) const;
第一个const表示返回的是一个const Student对象;
第二个const表示不会对括号内的对象(显式调用的对象)进行修改;
第三个const表示不会对调用此方法的对象(隐式调用的对象)进行修改。