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: [email protected]
 * 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: [email protected]
 * 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: [email protected]
 * 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: [email protected]
 * 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。

假设这篇博文对您有帮助,为了好的网络环境,不建议转载,建议收藏!假设您一定要转载,请带上后缀和本文地址。

时间: 2024-10-08 18:08:16

C/C++:多个.cpp文件包括同一个.h头文件定义方法的相关文章

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_

c中头文件在cpp文件里引用和.h文件引用的思考

我们在编敲代码中头文件是常常使用的. 可是头文件是应该包括在.H文件里还是在.cpp文件里.在这个其中有什么样去差别呢. 假如说我们编写了一个a.cpp  .我们将a.cpp文件的变量和函数申明在a.h中. 在a.h文件有使用了b.中定义的类型type1数据m_type,相同b.cpp的头文件一些变量也声明在b.h中. 此时我们当然能够在a.cpp中包括b.h 也能够在a.h中.这样都是可行的.由于我们编译的时候会会将b.h包括进来. 而.h文件是不參与编译的.然后我们继续深入. 假如我们将b.

WIN10 64位下VS2015 MFC直接添加 halcon 12的CPP文件实现视觉检测

近段时间开始接触halcon,但是在VS2015里面使用,无论是配置还是生产EXE文件,都不如意. 加上网上的教程很多,经过多次测试,其实有很多地方无需修改,如果修改的太多也失去了直接添加封装的意义. 我的环境为 WIN10 64位 halcon12 用64位到处C++ 文件,VS2015免费共享版. (如果要生成32位的话,需要halcon12 用32位程序  导出C++,并且需要把VC切换为X86平台, 库目录改为 C:\Program Files\MVTec\HALCON-12.0\lib

VS 2010不显示头文件源文件和所有以前分类的文件夹,*.h 和*.cpp都显示在同一个文件

打开VS后不显示头文件源文件和所有以前分类的文件夹,*.h 和*.cpp都显示在同一个文件 点击右图红色指示显示所有文件夹按钮,就能恢复.

避免同一个文件被include多次的方法

C/C++中有两种方式避免同一个文件被include多次 一种是#ifndef方式,一种是#pragma once方式: 方式一: #ifndef __SOMEFILE_H__ #define __SOMEFILE_H__ ... ... // 声明.定义语句 #endif 方式二: #pragma once ... ... // 声明.定义语句 #ifndef的方式受C/C++语言标准支持.它不光可以保证同一个文件不会被包含多次,也能保证内容完全相同的两个文件(或者代码片段)不会被不小心同时包

如何在安卓环境下自动编译所有cpp文件

正常情况下,需要在Android.mk文件下面一个一个手动添加cpp文件,如果文件较多,这样就太麻烦了. 解决办法如下: 把Android.mk文件里面的这段代码: LOCAL_SRC_FILES := hellocpp/main.cpp ../../Classes/AppDelegate.cpp 改为: FILE_LIST := hellocpp/main.cpp FILE_LIST += $(wildcard $(LOCAL_PATH)/../../Classes/*.cpp) LOCAL_

Makefile一个cpp文件依赖于多个header文件的陷阱

我一直以为,如果一个A.cpp文件中有多少条 #include "xxx.h"指令,在写Makefile的时候A.obj的依赖项除了A.cpp之外,就是A.cpp之内所有的 xxx.h 比如,如果A.cpp中有 #include "A.h" #include "B.h" #include "C.h",那么在Makefile中就有:A.obj: A.cpp A.h B.h C.h 但是 下面的例子是说明了,上面的想法是错误的 先

使用CL命令编译cpp文件

缘起,我的vs 2003无法新建工程,又不喜欢用vs 2013那样的重量级开发工具(就写两行代码,测试测试一些基本的语法规则或算法). 想来vs应该可以像GCC或G++那样直接用命令行编译Cpp文件,那样就省得我那么麻烦了. 我的步骤是这样的: 1. 打开Visual Studio .NET 2003 命令提示 进入cmd界面 2. cd  D:\proj2003\pureCode切换到cpp所在目录 D:\proj2003\pureCode>cl calcsize.cpp 3. 这样就会在当前

做一个懒COCOS2D-X程序猿(一)停止手打所有cpp文件到android.mk

前言:"懒"在这里当然不是贬义词,而是追求高效,拒绝重复劳动的代名词!做一个懒COCOS2D-X程序猿的系列文章将教会大家在工作中如何偷懒,文章篇幅大多较短,有的甚至只是几行代码,争取把懒发挥到极致! 一.懒人说书 Android.mk中LOCAL_SRC_FILES需要罗列出所有参与编译的文件,这样在.cpp文件少的时候还可以一个一个添加,当有几百个文件的时候会十分的痛苦! 我们下看看TestCpp工程中的Android.mk文件: 这只是节选的一部分,大概只有50个左右吧,除数量多