C/C++:多个.cpp文件包括同一个.h头文件定义方法
本文解决multiple definition of `XX'的错误。【出于反爬虫的目的,你不是在http://blog.csdn.net/zhanh1218上看到的,肯定不是最新最全的。】
关于头文件的定义中,请一定加上下面代码(此为头文件保护符):
<span style="font-size:14px;"><span style="font-size:12px;">#ifndef PERSON_H_
#define PERSON_H_
// 你的代码块
#endif /* PERSON_H_ */</span></span>
当中PERSON_H_为保护符的名字,一般建议与类名保持一致!样例中我的类名为Person.h。
每当编译器遇到#include时,都要去编译相关代码块,可是编译器不知道是不是已经编译过了,假设编译过了还去编译,那是不是等于代码块写了两次呢?所以,须要有不反复编译的机制,而这个机制正式以上代码。
详细实现为:#ifdef当且仅当变量已定义时为真,#ifndef当且仅当变量没有定义时为真。一旦检測结果为真,则运行兴许操作直至遇到#endif。
也就是说:假设首次include "Person.h",PERSON_H_是未定义,此时,编译器会define这个保护符,并运行代码块的编译!直到遇到#endif。下次遇到这个保护符,就不会运行代码块的编译了。这种机制保证了不会反复编译。
实际使用中,我发现,单个cpp文件里多次include 同一个.h头文件或者头文件里多次include某个头文件,不会有问题。可是,多个cpp文件都include 同一个.h头文件时,这样会出问题。问题是类外定义的非static及非inline函数还是会报multiple definition of `XX'的错误。【也就是说:#define的作用域仅仅是单个.cpp,而不是全局全部的.cpp文件】
终于解决方法是:仅仅在头文件定义类的申明和类的主体定义(也就是{}内的内容),在一个同名的.cpp文件中定义类外函数的实现!问题完美解决。所以,就算是大神写的书,书上也不全然是对的,或者表述的所有都清楚。
那么为什么头文件能够定义成下面形式呢?而不是仅仅申明,不定义类体呢?
<span style="font-size:14px;"><span style="font-size:12px;">class A
{
// 类定义
};</span></span>
类的定义,仅仅是告诉编译器,类的数据格式是怎样的,实例话后对象该占多大空间。 类的定义也不产生目标代码。因此它和普通变量的声明唯一的差别是不能在同一编译单元内出现多次。
还有一个原因就是,类能够在多个.cpp文件中重定义,变量却不行,除非用extern或者staic修饰的变量。
至于普通变量:同意static型的变量的定义;同意extern申明(不能定义!);直接申明比如int a; 是不行的,也是多次又一次定义。
extern表明该变量在别的地方已经定义过了,在这里要使用那个变量;static 表示静态的变量,分配内存的时候,存储在静态区,不存储在栈上面。【一篇不错的Blog:点击打开链接】
以下是代码演示样例,此实例部分为C++ Primer练习题。【反爬虫,第二天更新代码!】
/********************************************************************** file_name: vector_test.cpp** Created on: 2014年6月28日 下午3:34:23* Author: The_Third_Wave, Blog: http://blog.csdn.net/zhanh1218* Email: zhanh121823@sina.com* Last modified: 2014年6月28日 下午3:34:23*********************************************************************/#include <iostream>
#include <vector>
#include <string>
#include "Headers/Person.h"extern int k;
int main()
{std::vector<Person> per = {{"The_Third_Wave", 100, "Blog: http://blog.csdn.net/zhanh1218"}}; // 类初始化+vector初始化,所以{{}, {}}必须的for (auto &p: per){print(std::cout, p);}
}
/********************************************************************** file_name: ddqdq.cpp** Created on: 2014年6月28日 下午10:28:42* Author: The_Third_Wave, Blog: http://blog.csdn.net/zhanh1218* Email: zhanh121823@sina.com* Last modified: 2014年6月28日 下午10:28:42*********************************************************************/
#include <iostream>
#include <vector>
#include "Headers/Person.h"extern int k;
/********************************************************************** file_name: Person.h** Created on: 2014年6月28日 下午11:47:08* Author: The_Third_Wave, Blog: http://blog.csdn.net/zhanh1218* Email: zhanh121823@sina.com* Last modified: 2014年6月28日 下午11:47:08*********************************************************************/#ifndef PERSON_H_
#define PERSON_H_
/*****************************BEGIN***********************************/
#include <iostream>
#include <string>
using namespace std;
extern int a;
class Person
{friend istream &read(istream &is, Person &item);friend ostream &print(ostream &os, const Person &item);
public:Person() = default;Person(const string &n, unsigned int a, string add):name(n), age(a), address(add) { }Person(istream &);string Name() const {return name;}unsigned int Age() const {return age;}string Address() const {return address;}private:string name = "";unsigned int age = 1;string address = "";
};inline
Person::Person(istream &is)
{read(is, *this);
}
/******************************END************************************/
#endif /* PERSON_H_ */
/********************************************************************** file_name: Person.cpp** Created on: 2014年6月28日 下午10:55:32* Author: The_Third_Wave, Blog: http://blog.csdn.net/zhanh1218* Email: zhanh121823@sina.com* Last modified: 2014年6月28日 下午10:55:32*********************************************************************/
#include <iostream>
#include <string>
#include "Person.h"
using namespace std;istream &read(istream &is, Person &item)
{is >> item.name >> item.age >> item.address;return is;
}
ostream &print(ostream &os, const Person &item)
{os << item.name << " " << item.age << " " << item.address << endl;return os;
}
还有不懂的请留言。
本文由@The_Third_Wave(Blog地址:http://blog.csdn.net/zhanh1218)原创。还有未涉及的,会不定期更新,有错误请指正。
假设你看到这篇博文时发现不完整,那是我为防止爬虫先公布一半的原因,请看原作者Blog。
假设这篇博文对您有帮助,为了好的网络环境,不建议转载,建议收藏!假设您一定要转载,请带上后缀和本文地址。
C/C++:多个.cpp文件包括同一个.h头文件定义方法相关推荐
- 进一步学习WDK驱动程序的SOURCES文件、WMI驱动程序的mof文件和wmidata.h头文件
Win7 WDK 自带示例,wmi,wmisamp驱动程序,未构建之前,文件如下: 看一下其sources文件: TARGETNAME=WmiSamp TARGETTYPE=DRIVERKMDF_VE ...
- graphic头文件函数_graphics.h头文件
graphics.h头文件是一款tc操作必备组件.graphics.h头文件主要是运行在win8.win7操作系统上,为用户提供了非常多函数类型,用户只需使用tc编译就可以使用这个软件,是用户进行tc ...
- graphic头文件函数_graphics.h头文件中文版
graphics.h头文件中文版是一款tc操作运行必备组件,为用户提供非常丰富的图形函数,所有图形函数的原型均在graphics. h中,用户只需使用tc编译就可以使用graphics.h头文件中文版 ...
- std.h对应linux头文件,bits/stdc++.h头文件介绍(包含源代码)
注:转自http://blog.csdn.net/charles_dong2/article/details/56909347,同为本人写的,有部分修改. 之前在一个小OJ上刷题时发现有人是这么写的: ...
- graphic头文件函数_graphics.h头文件详解
r getlinesettings(struct linesettingstype far *lineinfo); 该函数将有关线的信息存放到由lineinfo 指向的结构中, 表中linesetti ...
- C++ .h(头文件) 与 .cpp(源文件) 的使用
.h 文件: .h是头文件 ,里面主要是写类的声明(包括类里面的成员和方法的声明).函数原型.#define常数等, 注意.h文件写的时候有特定的格式就是开头和结尾 #ifndef TEST_HEAD ...
- c语言中.h文件和.cpp文件解析
理论上来说cpp文件与头文件里的内容,只要是C语言所支持的,无论写什么都可以的,比如你在头文件中写函数体实现,任何一个cpp文件包含此头文件就可以将这个函数编译成目标文件的一部分(编译是以cpp文件为 ...
- include.cpp(main函数的cpp文件)文件中包含另一个.cpp文件的错误及原因
当一个main函数的cpp文件包含另一个cpp文件,使用#include "data.cpp" 是不可以的,例如下面 include.cpp #include <stdio ...
- .h文件和.cpp文件组织结构
1.包含关系: .h文件一般包含在.cpp文件中,.h文件中多为变量和类的声明,而.cpp文件才是变量和类中函数的真正定义. 但是#include <iostream> 这个文件既不是.c ...
最新文章
- 给迷茫的程序员一些中肯建议,你还在虚度光阴吗?
- 如何用Dart写一个单例
- 每日记载内容总结44
- docker 端口被占用问题解决
- 在C#中使用Irony实现SQL语句的解析
- jetty java_Jetty,Java和OAuth入门
- 编写高质量代码改善C#程序的157个建议——建议130:以复数命名枚举类型,以单数命名枚举元素...
- navicat远程mysql_navicat 远程连接mysql
- coreldraw凹槽_CorelDRAW教程 打造逼真静物写生油画
- 如何使用@vue/cli 3.0在npm上创建,发布和使用你自己的Vue.js组件库
- 【缺陷检测】基于matlab GUI形态学PCB电路板缺陷检测【含Matlab源码 821期】
- 好用小工具及文章推荐推荐
- 老男孩教育学习linux决心书
- Flutter 错误解决Building with plugins requires symlink support.
- 天猫年货节助手、京东年货节助手,自动完成任务领取奖励,解放双手
- python str转list
- 聊一下“深度学习”的基本思想
- 小米5aosp android p,为小米5刷入Lineage OS 15.1
- 是对马的鬼魂日本RPG
- Wireshark各版本下载地址
热门文章
- PPPOE/PPPOA白皮书小结
- 个人管理 - 目标管理之前,你会时间管理吗
- 05年之前我的程序员生涯
- webpack 配置react脚手架(四):路由配置
- Forbid consumer 192.168.85.1 access service com.sharearn.dubbo.romote.TestService from registry
- 【大型网站技术实践】初级篇:借助LVS+Keepalived实现负载均衡
- Javascript prototype理解
- WDS部署操作系统之二 制作并捕获模板计算机映像
- 磁盘被占满 系统出现 no space left on 报错(block被占满/inode被占满)
- 第18章 多线程----线程同步