《现代c++程序设计》(美)Barbara Johnston----2:类和对象

“这项工作有谁来完成”这个问题对于设计类和使用对象来说非常重要。

在编写程序之前,很重要的一步就是问问自己需要哪些类,每个类分别完成什么功能。

如下是一些以前使用过的类:

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()完成这个对象特有的清理工作,然后释放掉这个对象占有的内存,整个对象也就销毁了。

 

posted @ 2017-07-28 21:46  sky_lover  阅读(272)  评论(0编辑  收藏  举报