系统学习图像算法Day.29——C++基础——多文件编译、内存模型、命名空间

本篇内容主要讲解C++项目的三个大方面:多文件编译、内存模型、命名空间

(一)单独编译

首先明白:C++鼓励程序员将组件函数放在独立的文件中,可以单独编译这些文件,然后将它们链接成可执行的程序。
在这里插入图片描述
在VS编译器中就是如上图。

头文件一般包含:

①函数原型
②使用#define或者const定义的符号变量
③结构体声明
④类声明
⑤模板声明
⑥内联函数

其他的文件:

函数定义

必要的文件:

①main()函数
②使用 其他文件中定义的函数 的函数

示例
↓ 头文件:coordin.h ↓

//文件名:coordin.h
#ifndef COORDIN_H_      //
#define COORDIN_H_
struct polar    //极坐标数据
{
 double distance;
 double angle;
};
struct rect  //直角坐标数据
{
 double x;
 double y;
};
//函数原型
polar rect_to_polar(rect xypos);
void show_polar(polar dapos);
#endif

↓ 文件:函数定义.cpp ↓

//文件名为:函数定义.cpp
#include<iostream>
#include<cmath>
#include"coordin.h"//结构体定义,函数模板
//转换直角坐标系到极坐标系
polar rect_to_polar(rect xypos)//接收直角坐标数据,输出极坐标数据
{
 using namespace std;//标准名称空间
 polar answer;//定义极坐标结果结构变量
 answer.distance = sqrt(xypos.x*xypos.x+xypos.y*xypos.y);//开平方
 answer.angle = atan2(xypos.y,xypos.x);//反正切函数
 return answer;//返回极坐标形式的数据,以结构形式
}
void show_polar (polar dapos)//显示转换结果,以极坐标形式
{
 using namespace std;
 const double Red_to_deg = 57.29577951;//角度转换常数
 cout << "distance = " << dapos.distance;
 cout << ", angle = " << dapos.angle*Red_to_deg;
 cout << "degrees\n";
}

↓ 文件:main.cpp ↓

//文件名:main.cpp
#include<iostream>
#include"coordin.h"//本文件中的结构和函数在coordin.h中定义和使用原型
using namespace std;//名称空间
int main()
{
 rect rplace;//直角坐标结构变量x and y
 polar pplace;//极坐标结构变量
 cout << "Enter the x and y values";
 while(cin >> rplace.x >> rplace.y)//输入值
 {
  pplace = rect_to_polar(rplace);
  show_polar(pplace);
  cout << "next two number (q to quit):";
 }
 cout << "BYE!\n";
 return 0;
}

运行时,就是在IDE中生成项目,然后执行main文件,这三个文件就会自动链接好。

注意:

我们包含自己编写的头文件时,用的是 “coordin.h” 而不是 <coordin.h>

这两个符号对编译器来说区别很大,当头文件在<>里面时,C++编译器在存储标准头文件的主机系统的文件系统中查找; 如果头文件是在 " "里面,那么编译器将首先查找当前的工作目录或源代码目录

同一个文件中只能包含同一个头文件一次

为了避免这种情况发生,C++引入了 预处理器编译指令 #ifndef … #endif

(二)存储持续性、作用域、链接性

首先需要了解C++关于内存的一个最基本事实:
编译器使用三块独立的内存:
C++按照数据保留在内存中的时间(存储持续性),将存储分为3类(其实是4类,但有一类这里不做说明)

自动存储:这是最常见的存储方式,就是针对在函数定义中声明的变量,在程序开始执行其所属的函数或代码块时被创建,在程序执行完函数或者代码块时,该内存被释放。

静态存储:在函数定义外定义的变量 和 使用关键字 static 定义的变量,只要程序还在运行,该内存就一直都在

动态存储:用 new 运算符分配的内存一直存在,知道 delete 运算符将其释放。

ok,这样就对C++存储有个基本的了解,现在再继续讲另外两个名词:作用域、链接性

作用域:描述名称在文件的多大范围可见

作用域为局部:该变量只在定义它的代码块中可用(代码块就是由花括号括起来的一系列语句)
作用域为全局:在该变量定义位置到文件结尾都可用

链接性:描述了名称如何在不同单元共享。

链接性为外部:可在文件间共享
链接性为内部:只能在一个文件中的函数共享

好,搞懂了以上的概念,我们接下来对几种存储做分析

①自动存储

作用域链接性
局部无链接性
int main()
{
	int a = 5;   //a 这个内存在 main() 函数中都存在,且可见
	{
        	int b = 22;   // b在他所在这个花括号中可见,花括号结束则内存被释放
        	int a = 9;    // a由于与外面的a重名,此时,这里的a可见,外面的a暂时隐藏,但外面的a仍占有内存
        	cout << a;    //输出 9
	}
        cout << a;            //输出 5
}

上面这个程序很好地解释了作用域与可见性。

②静态存储

作用域链接性
全局(除无链接性静态变量)外部链接性、内部链接性、无链接性
...
int a = 1000;    //静态存储、具有外部链接性
static b = 50;   //(加上static)静态存储、具有内部链接性

int main()
{
	...
}

void funct1( int n )
{
	static int c = 0;  //静态存储、无链接性(只能在该函数中使用它,但即使该函数没有被执行,其内存也一直存在)
}
...

就这个 具有外部链接性的静态变量 展开讲一讲应用:

// file_1.cpp
int dogs = 30;   // 定义具有外部链接性的静态变量
int cats = 40;

// file_2.cpp
extern int dogs; //使用关键字 extern 引用file1文件中的静态变量
extern int cats;
static int dogs = 5;  //当在这个文件想命名一个同名的静态变量时,应该使用内部链接性的变量,不然违反单定义规则;

C++单定义规则:
变量只能有一次定义。两种变量声明:定义变量(分配内存)、引用声明(不分配内存)

const限定符限定的字符常量: 相当于 内部链接性静态全局变量

函数:默认为 外部链接性静态存储(可以在文件间共享,别的文件引用该函数时可用可不用extern,只能有一个文件包含该函数定义,但每个文件应该有其声明),可用static将函数设为内部链接性。

③动态存储
不受作用域与链接性控制,仅由new和delete控制

(三)名称空间

背景问题:当使用多个厂家提供的类库时,可能导致名称冲突,我如何控制每个名称的作用域
两个术语:

声明区域:可以在其中进行声明的区域
潜在作用域:从声明点开始 到 齐声明区域的末尾

下面程序演示如何利用创建命名空间避免名称冲突

namesapce Jack       // 利用 namespace 创建一个命名的 名称空间
{
	double dog;
	int cat;
	void funct1();
	struct people
	{
		...
	}
}

int main()
{
	Jack::cat = 30;   //使用作用域解析运算符 :: 访问命名空间中的名称
	
	using Jack::dog;  //using声明,使特定的标识符可用,鼓励的方式
	dog = 410.0;

	using namespace Jack;  //using编译,使该命名空间的所有名称可见,一般不鼓励,会有冲突风险
	dog = 300.0;
	cat = 40;
}

对于using声明,最好将其作用域设置为局部,而不是全局。这个取决于你的 using Jack::dog; 语句放在哪,是在main()函数前面,还是哪个花括号中。

好文

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值