“这项工作有谁来完成”这个问题对于设计类和使用对象来说非常重要。
在编写程序之前,很重要的一步就是问问自己需要哪些类,每个类分别完成什么功能。
如下是一些以前使用过的类:
string 处理文本数据
vector 数据列表
queue 队列,先入先出
ifstream 打开数据文件并读取文件
ofstream 打开数据文件并写入文件
要使用这些类,需要在程序文件的开头包含对应的库文件,然后就可以创建对象来完成特定的工作。
对象后面跟一个点运算符的方式来访问类中的定义功能
编写自己的类
类的定义格式:
通常,会在public部分定义类的行为,提供公共的函数接口供外部访问;在protected部分,定义遗传特性;在private部分,定义这个类私有的属性和行为。
与类成员的访问控制类似,派生方式也有三种:public派生,所有全部继承,不做改变,如Teacher类从Human类中派生;private派生,把基类的所有公有(public)成员都变成自己私有的,这样派生类不在直接支持基类的公有接口,它只希望可以重用基类的实现而已;protected派生,把基类的所有公有(public)成员都变成protected类型,保护基类的所有接口不被外界访问,只能由自身及自身的派生类访问。
c++程序都遵循这样一个惯例:将类的声明保存在于类名称相同的头文件(*.h)中,而类成员函数的实现代码保存在同名的*,cpp中,例如Data.cpp。
因此,一个类的代码往往保存在一对文件中,例如Date.h和Date.cpp。这样可以方便代码的复用,只要把一个类的两个文件加入到工程中就可以使用了。参见C++中的头文件和源文件
具体例子:
整个程序包含一个头文件.h,和2个.cpp源文件,如下
代码:
.h文件,负责类的声明
#pragma once //防止一个 头文件被多次编译 #include<string> using namespace std; class VolumeCalc { private: double sphRadius; double boxLength, boxWidth, boxHeight; double sphVolume, boxVolume; void CalcBoxVol();//被set函数调用 void CalcSphVol(); public: VolumeCalc(); //类的构造函数,创建对象时,会自动调用的成员函数 void SetSphRadius(double r); void SetBoxDim(double l, double w, double h);//set函数总是负责把数据传入到类中,get函数负责从类中取出数据 double GetSphVol() { return sphVolume; } double GetBoxVol() { return boxVolume; }//函数简单的话直接在里面定义了就 };
同名的.cpp负责函数 的实现,
//包含volume cal类 的一些函数定义 #include"VolumeCalc.h" #include<cmath> using namespace std; VolumeCalc::VolumeCalc() //构造函数 { boxHeight = boxWidth = boxLength = 0.0; sphRadius = 0.0; boxVolume = sphVolume = 0.0; } //set函数在收到新数据之后就调用calcula函数 void VolumeCalc::SetSphRadius(double r) { sphRadius = r; CalcSphVol(); } void VolumeCalc::SetBoxDim(double l, double w, double h) { boxLength = l; boxWidth = w; boxHeight = h; CalcBoxVol(); } void VolumeCalc::CalcBoxVol() { boxVolume = boxHeight*boxLength*boxWidth; } void VolumeCalc::CalcSphVol() { double PI = 3.14159265; sphVolume = 4.0 / 3.0*PI*pow(sphRadius, 2); }
另一个为主函数:
#include<iostream> #include"VolumeCalc.h" //#include<cmath> .h头文件已经包含,可以略去 using namespace std; int main() { cout << "calculation volume of a" << " box or a sphere" << endl; VolumeCalc Bob; //创建对象,让BOb替我们来完成计算 //使用局部变量len,wid等来保存用户输入的数据 double len, wid, hgt; double rad; cout << "Box : ENTER the length width and geight \n"; cin >> len >> wid >> hgt; cout << "Box : ENTER the radius \n"; cin >> rad; Bob.SetBoxDim(len, wid, hgt); Bob.SetSphRadius(rad);//set函数总是负责把数据传入到类中,get函数负责从类中取出数据 //其实。类不过是扩展我们可以使用的数据类型,也不用想的有多么难 //现在,让Bob告诉我们计算的数据结果, //调用对象的get函数 double sphereV = Bob.GetSphVol(); double boxV = Bob.GetBoxVol(); cout.setf(ios::fixed); cout.precision(3); cout << "\n box volume :" << boxV << "\n sphere volume :" << sphereV; cin.get(); cin.get(); return 0; }
关于析构函数:
new关键字创建一个指向对象 的指针,
//创建一个新的对象,并让pMrChen指针指向这个新的对象
Teacher* pMrChen = new Teacher(); //之前已经定义了Teacher类
这里,使用“new”关键字创建了一个Teacher类的对象,“new”关键字会调用Teacher类的构造函数来 完成对象的创建,并返回这个对象 的地址,再将这个返回的对象地址赋值给pMrChen指针,这样就同时完成了对象 的创建和指针的赋值。
有了指向对象的指针,就可以利用“-->”运算符,通过指针访问该对象 的成员。
要特别注意的是,跟普通的变量不同,使用new关键字创建的对象无法在结束其生命周期的时候自动销毁,所以必须使用“delete”关键字销毁这个对象,释放其占用的内存。
如: delete pMrChen;
"delete"首先会调用Teacher类的析构函数~Teacher()完成这个对象特有的清理工作,然后释放掉这个对象占有的内存,整个对象也就销毁了。