多文件结构与预处理

1 C++程序的一般组织结构

C++程序通常由多个源文件组成,每个文件的职责可以如下划分:

  • 类声明文件(.h文件):定义类和其接口(函数与数据成员)。
  • 类实现文件(.cpp文件):实现类的具体功能。
  • 主程序文件(.cpp文件):包含 main()函数,调用类或函数完成程序任务。

例子(Point类的多文件组织):

  1. Point.h

    • 包含类的定义和接口声明。
    class Point {
    public:
        Point(int x = 0, int y = 0) : x(x), y(y) { }
        Point(const Point &p);
        ~Point() { count--; }
        int getX() const { return x; }
        int getY() const { return y; }
        static void showCount();
    private:
        int x, y;
        static int count;
    };
    
  2. Point.cpp

    • 包含类的实现。
    #include "Point.h"
    #include <iostream>
    using namespace std;
    
    int Point::count = 0;
    
    Point::Point(const Point &p) : x(p.x), y(p.y) {
        count++;
    }
    
    void Point::showCount() {
        cout << "Object count = " << count << endl;
    }
    
  3. 5_10.cpp

    • 包含主程序。
    #include "Point.h"
    #include <iostream>
    using namespace std;
    
    int main() {
        Point a(4, 5);
        cout << "Point A: " << a.getX() << ", " << a.getY();
        Point::showCount();
    
        Point b(a);
        cout << "Point B: " << b.getX() << ", " << b.getY();
        Point::showCount();
        return 0;
    }
    

编译过程将 Point.cpp5_10.cpp编译成目标文件并链接生成可执行文件。


2 外部变量与外部函数

  • 外部变量

    • 定义在文件作用域中的变量,默认是外部的,可被其他文件访问。
    • 其他文件需用 extern声明它们。
    // 文件1
    int globalVar;
    
    // 文件2
    extern int globalVar;
    
  • 外部函数

    • 定义在类外部的函数,可跨文件调用。需要在调用之前声明其原型。
    • 也可以用 extern修饰,功能相同。

限制外部访问的方法:

  • 使用匿名命名空间,变量和函数不会暴露到其他编译单元。

    namespace {
        int n;
        void f() {
            n++;
        }
    }
    

3 标准C++库

  • 标准C++库提供可重用的组件,主要包括:
    1. 输入/输出类
    2. 容器类与抽象数据类型(ADT)
    3. 存储管理类
    4. 算法
    5. 错误处理
    6. 运行环境支持

4 编译预处理

包含指令(#include)

  • #include <文件名>:从标准路径搜索头文件。
  • #include "文件名":从当前目录搜索,找不到时按标准路径搜索。

宏定义指令(#define)

  • 定义符号常量:

    #define PI 3.14159
    
  • 定义带参数的宏:

    #define MAX(a, b) ((a) > (b) ? (a) : (b))
    
  • 常用的 const或内联函数可以取代宏定义。

条件编译指令

  1. #if ... #endif

    :根据条件编译代码。

    #if defined(DEBUG)
    // 调试代码
    #endif
    
  2. #ifdef#ifndef

    • 检查是否定义了某个符号,常用于防止头文件重复包含。

      #ifndef HEAD_H
      #define HEAD_H
      class Point { ... };
      #endif
      

5 总结

多文件结构和编译预处理命令使C++程序模块化、易于维护和扩展。编译预处理则为灵活控制代码的编译和组织提供了强大支持。