zoukankan      html  css  js  c++  java
  • 对C++文件组织及全局对象的理解

    关于头文件和源文件的文件类型

    头文件定义函数、类、变量的声明,告诉编译器这个项目中有哪些对象,源文件才是实现代码,为了在模块间共享,一般都是把声明和实现分开,需要哪个模块时就include那个模块的h文件。

    编译器对文件类型是没有严格要求的,源文件和头文件名也不需要严格保持一致,但是为了直观,便于阅读,习惯上用cpp作为源文件,h作为头文件,文件名保持一致。

    需要注意的是,h中声明的函数,cpp不需要包含这个h也能编译,似乎编译器能过根据函数定义在所有模块中自动寻找实现代码,只要保证项目中函数名称唯一就可以了。而类、结构等cpp文件必须包含h,因此每个cpp包含自己的h还是必须的。

    关于模块包含

    由于声明和实现分开,每个cpp必须include自己的h文件。加上所有cpp必须引用预编译头。

    #include "stdafx.h"

    这时会引发一些混乱,一般都希望将相对不变的公共模块的h文件include到stdafx.h中,这样可以减少编译时间,也方便维护。但是假如有一个公共类模块的h文件被包含在stdafx.h中,如果该类的cpp同时包含了stdafx.h和自己的h文件,就会出现重复定义的错误。应该把cpp里去掉include自己的h文件,也可以使用下面的方法。

    防止交叉重定义

    在每个cpp文件中加上以下代码

    VC6中:
    #if !defined(XXXX_XXXX) //xxxx部分使用文件名和特殊字母定义,以作区别,且必须大写
    #define XXXX_XXXX
    #if _MSC_VER > 1000
    #pragma once
    #endif // _MSC_VER > 1000
    .......//这里变量和函数声明部分
    #endif

    VS2008中简单了:

    #pragma once

    连接时全局对象和extern以及重定义的问题

    虽然上面的方法可以避免重定义,但也只是针对单一模块来说的,由于编译时是单个模块分别编译生成obj文件的,通过上面两种方式处理编译是没问题了,因为每处理一个cpp时是不考虑其他cpp有些什么东西的,但是在链接时链接器发现了多同名对象而出错。比如说在stdafx.h中定义了一个int a;,那么所有cpp都会包含它,使得整个项目中所有obj都存在一个int a,连接时因为发现多个定义而报错。

    解决方法是:

    对于全局对象(包括普通变量),在stdafx.h中以extern修饰定义(也可以单独把所有全局对象以extern修饰写在一个h文件中再包含到stdafx.h),然后在任意一个cpp中声明,只在一个cpp中定义一次即可,其他cpp就可以使用该对象了。如此,连接器在遇到使用该对象时会在所有obj定位该对象。一般把全局对象的定义写在主程序所在cpp中。

    关于全局函数,模块中如要调用一个全局函数必须包含了该函数的h文件,因此函数所在h文件包含到stdafx.h文件中就形成了全局函数,由于函数不是不是对象实例,不会出线连接错误。

  • 相关阅读:
    Nginx 配置文件
    Nginx 目录结构
    Nginx 功能模块
    logrotate日志管理工具
    Nginx 编译安装
    CentOS7安装Tomcat
    springcloud如何实现服务的平滑发布
    springcloud zuul聚合微服务的swagger文档
    alibaba的springcloud孵化器项目
    springcloud灰度发布实现方案
  • 原文地址:https://www.cnblogs.com/CodeBlove/p/899515.html
Copyright © 2011-2022 走看看