CPP-类的位置(Placement of class)

当写简单程序时候,所有东西可以放在一个文件中,但程序较大时,这样做并不明智。前面我们讨论过如何将程序分割,即应该成对的构建程序文件。对每个函数定义文件(definition),应该有相应的函数声明头文件(declaration). 对类,我们有类似的原则。即应该成对的创建文件,一个头文件和一个定义文件类的定义被放在头文件中,相应的定义文件放置成员函数的定义,只有内联函数的实现才可以放在头文件中,其它成员函数的实现应该放在另外一个单独的cpp文件之中。如果我们有一组类,他们彼此相似,那我们可以将几个类的定义放在同一个头文件中。此时,定义文件应该包含所有类的成员函数的定义。

class MyClass // class declaration

暗示名字MyClass定义了一个类,他的完整定义将稍后出现。

看一个例子:类Flight, 描述一般航班。头文件名字flight.h,包含了类Flight的定义。文件看起来如下:

//The file flight.h
#ifndef FLIGHT_H
#define FLIGHT_H
#include "clock.h"
#include <string>
using namespace std;
class Flight{
public:
void init(string flight_no,
          int dep_h,int dep_m,int arr_h,int arr_m);
void info();
void delay(int min);
private:
string no;
Clock dep,arr;
};
#endif

c++中,一个类不能定义多余一次。上术代码第2,3和最后一行用来防止flight.h在编译过程中被包含多余一次。FLIGHT_H是一个宏的名字,是一个我们自己定义的常数。第二行检查是否这个名字的宏被定义过(#ifndef means if not defined)。 如果没有定义,编译器将读取整个头文件,直到#endif。因此,此流程确保头文件不会被定义多于一次。因此,对所有包含类的定义的头文件都应采用此步骤。建议宏和头文件有相同的名字,但全部采用大写。
此类有三个数据成员:字符数组no,包含航班号,两个clocks,名字是dep和arr,暗示离开和达到时间。我们假设类Clock是在一个头文件为clock.h中定义,因此必须在程序中包含此头文件(第4行)。

Flight有三个成员函数,init用来初始化航班,航班号,离开和到达时间,info输出关于航班的信息。delay被调用当航班延误。延迟时间作为输入参数。函数delay将更新此航班离开和达到时间。

就函数而言,头文件不应该包含函数体的定义,仅仅是函数的声明。此原则对类同样适用。因此我们将成员函数的定义放在相应的定义文件“flight.cpp”中。

//the file flight.cpp
#include "flight.h"
#include <iostream>
#include<iomanip>
#include<string>

using namespace std;

void Flight::init(string flight_no,
                int dep_h,int dep_m,int arr_h,int arr_m)
{
    no = flight_no;
    dep.set(dep_h, dep_m, 0);
    arr.set(arr_h, arr_m, 0);
}

void Flight::info()
{
    cout << "Flight no " << no;
    cout << ", Dep "; dep.write(false);
    cout << ", Arr ", arr.write(false);
    cout << endl;
}

void Flight::delay(int min)
{
    for (int i = 1; i < min * 60; i++)
        dep.tick();
    for (int j = 1; j <= min * 60; j++)
        arr.tick();
}

为了使程序知道类的定义,flight.h必须要被包括,clock.h则不需要,因为他已经被包括在flight.h之中了。 数据成员dep和arr是类Clock的对象,Clock的成员函数用来处理这些对象。数据成员dep和arr不能直接访问,因为他们依赖类Clock的私有部分。
使用类Flight的程序必须包含flight.h。举例如下:

//the file main.cpp
#include "flight.h"

void main()
{
    Flight f;
    f.init("SK1853", 8, 10, 10, 55);
    f.delay(15);
    f.info();
    system("pause");
}

头文件不应该包含成员函数的单独定义,一个重要例外是inline函数,它必须在头文件中定义!!!
如clock.h可以看起来如下:


class Clock {
public:
    void set(int hour, int min, int sec);
    int read_hour() { return h; }
    int read_min() { return m; }
    int read_sec() { return s; }
    void write(bool write_sec = true);
    void tick();
private:
    int h, m, s;
};

inline void Clock::set(int hour,int min,int sec)
{
    h=hour;m=min;s=sec;
}

此处我们让函数read_hour,read_min,read_sec和set作为inline函数。 注意,如果函数set没有被定义为inline函数,它必须放在一个单独的文件clock.cpp之中!!!

综上,clock.h可以写成下面的样子:


class Clock {
public:
    void set(int hour, int min, int sec);
    int read_hour() { return h; }
    int read_min() { return m; }
    int read_sec() { return s; }
    void write(bool write_sec = true);
    void tick();
private:
    int h, m, s;
};

由于我们没有将set, write,tick函数定义为inline函数,因此我们需要一个单独的cpp文件来实现这些函数,clock.cpp文件如下:

#include "clock.h"
#include<iomanip>
#include <iostream>
using namespace std;
void Clock::set(int hour, int min, int sec)
{
    h = hour; m = min; s = sec;
}
void Clock::write(bool write_sec)
{
    std::cout << setw(2) << setfill('0') << h
        << ':' << setw(2) << setfill('0') << m;
    if (write_sec)
        std::cout << ':' << setw(2) << setfill('0') << s;
}
void Clock::tick()
{
    s = (s + 1) % 60;
    if (s == 0)
    {
        m = (m + 1) % 60;
        if (m == 0)
            h = (h + 1) % 24;
    }
}

此cpp文件中包含了clock.h中定义的另外三个非inline函数的实现。将flight.h,clock.h,flight.cpp,clock.cpp和main.cpp一起编译即可。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值