C++多文件结构和预编译命令

  • C++的一般组织结构

1、一个工程可以被划分为多个源文件:类声明文件(.h文件)

类实现文件:(.cpp文件)

类的使用文件(main()所在的.cpp文件)

2、利用工程来组合各个文件

例如:

//文件1,类的定义,Point.h
class Point { //类的定义
public:          //外部接口
       Point(int x = 0, int y = 0) : x(x), y(y) { count++; }
       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);      //定义对象a,其构造函数使count增1
       cout <<"Point A: "<<a.getX()<<", "<<a.getY();
       Point::showCount();      //输出对象个数
       Point b(a);         //定义对象b,其构造函数回使count增1
       cout <<"Point B: "<<b.getX()<<", "<<b.getY();
       Point::showCount();      //输出对象个数
       return 0;
}

上面的程序的编译链接过程如下:

C++多文件结构和预编译命令

  • 外部变量

如果一个变量除了在定义它的源文件中可以使用外,还能被其它文件使用,那么就称这个变量是外部变量。

文件作用域中定义的变量,默认情况下都是外部变量,但在其它文件中如果需要使用这一变量,需要用extern关键字加以声明。

  • 外部函数

在所有类之外声明的函数(也就是非成员函数),都是具有文件作用域的。

这样的函数都可以在不同的编译单元中被调用,只要在调用之前进行引用性声明(即声明函数原型)即可。也可以在声明函数原型或定义函数时用extern修饰,其效果与不加修饰的默认状态是一样的。

  • 将变量和函数限制在编译单元内

使用匿名的命名空间:在匿名命名空间中定义的变量和函数,都不会暴露给其它的编译单元。

例如:

namespace {         //匿名的命名空间
         int n;
         void f() {
                     n++;
         }
   }

这里被namespace{......}括起来的区域都属于匿名的命名空间。

标准C++库:

标准C++类库是一个极为灵活并可扩展的可重用软件模块的集合。标准C++类与组件在逻辑上分为6种类型:

输入输出类;

容器类与抽象数据类型;

存储管理类;

算法;

错误处理;

运行环境支持;

  • 编译预处理:

#include包含指令

将一个源文件嵌入到当前源文件中该点处。

#include<文件名> :按标准方式搜索,文件位于C++系统目录的include子目录下

#include"文件名": 首先在当前目录中搜索,若没有,再按标准方式搜索。

#define 宏定义指令:定义符号常量,很多情况下已被const定义语句取代;定义带参数宏,已被内联函数取代。

#undef :删除由#define定义的宏,使之不再起作用。

条件编译指令——#if 和 #endif

#if  常量表达式
 //当“ 常量表达式”非零时编译
     程序正文 
#endif
......

条件编译指令——#else

#if 常量表达式1
    程序正文1  //当“ 常量表达式1”非零时编译
#elif 常量表达式2
    程序正文2  //当“ 常量表达式2”非零时编译
#else
    程序正文3  //其他情况下编译
#endif

如下的条件编译指令:

#ifdef 标识符
    程序段1
#else
    程序段2
#endif

指:

如果“标识符”经#defined定义过,且未经undef删除,则编译程序段1;

否则编译程序段2;

如下的条件编译指令:

#ifndef 标识符
   程序段1
#else
   程序段2
#endif

指:

如果“标识符”未被定义过,则编译程序段1;否则编译程序段2.

单选题:

以下关于外部变量和外部函数的说法,错误的是:

1、外部变量的声明可以是引用性的声明

2、静态变量和静态函数即使使用extern声明,它们的使用范围仍然被限定在定义文件中

3、外部变量可以为多个源文件所共享

4、外部函数和外部变量在声明时,都不能省略关键字extern.

正确答案:4.有的不需要extern。