C++抽象编程——接口(2)——接口的用途

我们建立了一个接口,但是我们为什么要建立接口?它有什么用呢?我们写在同一个文件里不是更好吗?为什么要那么麻烦?接下来我们就慢慢的探讨吧。

出口数据类型(Exporting types)

前面部分中描述的error.h接口只是导出一个函数,没有其他的。 以后我们将在C++中使用的大多数接口还导出数据类型。这些类型中的大多数将是类,它们是C++提供的面向对象类型系统的基础。鉴于我们刚刚了解这些,我们就先不出口类了,先出口一个表示数据类型的枚举类型(enumerated types)的方位吧,我们都知道我们平时熟悉的方位,就是4个,所以我们可以是这样定义一个枚举类型:

enum Direction { NORTH, EAST, SOUTH, WEST };

通过库接口访问此类型的最简单的方法是编写一个只包含该行的direction.h接口以及通常的接口样板。 如果你采用这个策略,你根本不需要提供一个实现。
但是,更有用的是让这个接口导出一些简单的函数来处理Direction值。例如,定义一个directionToString函数是并用它来返回给定枚举值的方向的名称。对于稍后出现的一些程序,将leftFrom和rightFrom的函数返回到指定方向上转动90度,以便例如leftFrom(NORTH)将返回西。如果将这些函数添加到direction.h接口,您还需要提供一个direction.cpp文件来实现这些功能。所以我们可以这样写:

/*头文件*/
#ifndef _direction_h
#define _direction_h

#include <string>
/*声明枚举类型*/
enum Direction { NORTH, EAST, SOUTH, WEST };
/*声明处理该类型的函数*/
Direction leftFrom(Direction dir);//返回类型是Direction
Direction rightFrom(Direction dir);
std::string directionToString(Direction dir);

#endif

接下来是cpp文件:

#include <string>
#include "direction.h"
using namespace std;
/*定义direction上的函数*/
Direction leftFrom(Direction dir){
    return Direction((dir + 3) % 4);//返回该类型的值 
}
Direction rightFrom(Direction dir) {
    return Direction((dir + 1) % 4);
}
string directionToString(Direction dir) {
    switch(dir){
        case NORTH: 
            return "NORTH";
            case EAST:
                    return "EAST";
                    case SOUTH:
                        return "SOUTH";
                        case WEST:
                            return "WEST";
                            default:
                                return "???"
    }
}

现在你肯定对于

return Direction((dir + 3) % 4);

是怎么来的很感兴趣吧。我们可以先回顾一下枚举类型的特点:
在我们声明一个枚举类型之后,系统会为其自动赋值,按照顺序从0开始来赋值,比如NORTH = 0;EAST = 1;等等。所以我们对他们进行处理就是对这些数字进行处理。因此,问题就变得简单了。向右转就相当于在这基础值上加1,向左转的时候就是减去1,(如果我们画一个直角坐标系,然后标上东南西北,写上对应的数字就很好理解了),用%运算符,是为了避免特殊情况,比如3,加1就是4,但是我们最大就是3
为了加深理解,我们可以这样举例子:
当dir = 1(此时为东),执行左转后就是 (1+3)%4 = 0,为北。
这个时候你可能会说,我们也可以这样子算啊:

Direction leftFrom(Direction dir) {
    return Direction((dir - 1) % 4);
}

但是我们并没有这样子去算,理由很简单,当dir = 0 的时候(即方位为北的时候),就会出现越界的现象。

出口常数(Exporting constant definitions)

除了函数和类型之外,接口通常导出常量定义,以便多个文件可以共享该常量,而不会在每个源文件中重新定义它。例如,假设我们正在编写涉及几何计算的程序,则可以定义一个数学常数 π,其给定常数的常规约定,可能被称为PI。则我们可以写入:

const double PI = 3.14159265358979323846;

注意:在C++中,以此形式编写的常量对于包含它们的源文件是私有的,不能通过接口导出。 要导出常量PI,需要将关键字extern添加到其接口中的定义和原型声明中。

现在我们试着写一个gmath.h,导出PI以及一些简单的功能,简化以度为单位的角度工作。
头文件

#ifndef _gmath_h
#define _gmath_h

extern const double PI; //数学常数pi,并且我们加了关键字extern,以便导出

/* 返回一个角度的sin值
*用法 double sine = sinDegrees(angle);
*/ 
double sinDegrees(double angle);
/* 返回一个角度的cos值
*用法 double cos = cosDegrees(angle);
*/ 
double cosDegrees(double angle);
/*将弧度制变为角度制
*用法  double degrees = toDegrees(radians);
*/
double toDegrees(double radians);
/*将角度制变为弧度制
*用法  double radians = toRadians(degrees);
*/
double toRadians(double degrees); 

#endif

cpp文件

#include <cmath>
#include "gmath.h"
extern const double PI = 3.14159265358979323846;
double sinDegrees(double angle) {
    return sin(toRadians(angle));
}
double cosDegrees(double angle) {
    return cos(toRadians(angle));
}
double toDegrees(double radians) {
    return radians * 180 / PI;
}
double toRadians(double degrees) {
    return degrees * PI / 180;
}

测试文件

#include <iostream>
#include "gmath.h"
using namespace std;
int main(){
    cout << toRadians(30.0) << endl;
    cout << toDegrees(0.5236) << endl;
    cout << sinDegrees(30.0) << endl;
    cout << cosDegrees(60.0) << endl;
}

测试结果

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值