关于C++头文件重复包含的有关问题.求解

关于C++头文件重复包含的问题.求解

#ifndef PEOPLE_H
#define PEOPLE_H
#define _CRT_SECURE_NO_WARNINGS
#include <string.h>
#include <iostream>
int a = 0;  //这里只是多定义了一个变量.

class people
{
private:
char name[20];
int age;
public:
void set_name(char *s);
void set_age(int i);
const char * get_name();
const int get_age();
};
#endif


我知道在头文件定义变量是不规范的做法.我只是想了解.为什么即使在定义了宏的情况下.两个CPP文件包含该头文件依然会报变量a重复定义的错误.
------解决思路----------------------
定义宏的目的:防止同一个cpp文件包含多次.h(有的时候同一个cpp会间接的包含多次同一个.h)

你的问题:在.h中声明变量,在多个.cpp中包含,编译时会在多个.o文件中有这个变量,所以在链接的时候会出错
------解决思路----------------------
a是全局变量
B文件引用此头文件,不报错
C文件引用此头文件,不报错(没有重复定义)
此时,整个工程中    a变量因为是全局变量,就会被  定义两次,报错
------解决思路----------------------
#ifndef PEOPLE_H
#define PEOPLE_H
/* ... */
#endif

这样写能够防止头文件被重复包含

在头文件中定义变量不是不规范,而是一种错误。
原因在于
如果在header.h中定义一个变量。
int a = 0;
那么在
file1.c 里如果 #include "header.h"
那么在编译后的file1.o里就会定义一个全局变量a

同样的,
file2.c 里如果 #include "header.h"
那么在编译后的file2.o里就会定义一个全局变量a

在链接阶段,如果file1.o和file2.o链接在一起,变量a的定义就是重复的。

$ cat file1.c file2.c main.c header.h


/* file1.c */
#include "header.h"


/* file2.c */
#include "header.h"

/* main.c */
#include <stdio.h>

#include "header.h"

int main(void)
{
        printf("a=%d\n", a);
        return 0;
}

/* header.h */
#ifndef HEADER_H
#define HEADER_H

int a = 0;

#endif

$ nm file1.o file2.o main.o

file1.o:
0000000000000000 B a

file2.o:
0000000000000000 B a

main.o:
0000000000000000 B a
0000000000000000 T main
                 U printf

$ gcc -o demo file1.o file2.o main.o  
file2.o:(.bss+0x0): multiple definition of `a'
file1.o:(.bss+0x0): first defined here
main.o:(.bss+0x0): multiple definition of `a'
file1.o:(.bss+0x0): first defined here
collect2: ld 返回 1

正确的方法是,在header.h里声明变量,在一个单独的global.c文件里定义变量。


/* file1.c */
#include "header.h"


/* file2.c */
#include "header.h"

/* main.c */
#include <stdio.h>

#include "header.h"

int main(void)
{
        printf("a=%d\n", a);
        return 0;
}

/* header.h */
#ifndef HEADER_H
#define HEADER_H

extern int a;

#endif

/* global.c */
int a = 0;

$ gcc -c file1.c file2.c main.c global.c
$ nm file1.o file2.o main.o global.o

file1.o:

file2.o:

main.o:
                 U a
0000000000000000 T main
                 U printf

global.o:
0000000000000000 B a


------解决思路----------------------
a重复定义 一般这样用 
#ifndef INIT
#define DECLARE extern
#else
#define DECLARE // nothing!!!
#endif

DECLARE int a;

找一个cpp定义一个INIT, 包含头文件即可
------解决思路----------------------
你要搞清楚编译错误 和连接错误 

你每一个文件都是可以编译通过的,因为每一个文件里面都只有一个变量。

但是,在链接时,把各个文件链接成一个单独模块时,链接器发现各个文件都有同一个名字的变量,连接器没有办法把它们合并在一个模块里面。所以报错。

链接错误 和 编译错误是不一样的
------解决思路----------------------
定义成全局变量
使用的地方声明,就没这个问题
------解决思路----------------------
C/C++ 是以文件作为单独的编译单元的。
然后这些编译后的 .obj 文件有链接器链接成目标文件。