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

C++语言 码拜 10年前 (2015-07-10) 2152次浏览 0个评论
 

#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重复定义的错误.

 
#ifndef PEOPLE_H
#define PEOPLE_H
#endif

只是说明在在某一个编译单元不会重复包含,没有说在不同单元中不可以再次出现

5分

定义宏的目的:防止同一个cpp文件包含多次.h(有的时候同一个cpp会间接的包含多次同一个.h)

你的问题:在.h中声明变量,在多个.cpp中包含,编译时会在多个.o文件中有这个变量,所以在链接的时候会出错

5分

a是全局变量
B文件引用此头文件,不报错
C文件引用此头文件,不报错(没有重复定义)
此时,整个工程中 a变量因为是全局变量,就会被 定义两次,报错

15分

#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

5分

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

DECLARE int a;

找一个cpp定义一个INIT, 包含头文件即可

5分

你要搞清楚编译错误 和连接错误

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

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

链接错误 和 编译错误是不一样的

 
用宏定义只解决编译时不会重复的问题,并无法解决链接时的问题

3分

定义成全局变量
使用的地方声明,就没这个问题
 
引用 4 楼 mymtom 的回复:

#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

感谢耐心回复.如果一个CPP里定义了一个宏.可以作用在另一个CPP吗,当然是同一项目.
我以为在file1.cpp定义了一个PEOPLE_H宏,那么在file2.cpp里包含.h的时候.由于已经定义了宏PEOPLE_H,所以中间的代码就不参与编译了.难道file2.cpp也要再重新定义一次宏PEOPLE_H

2分

C/C++ 是以文件作为单独的编译单元的。
然后这些编译后的 .obj 文件有链接器链接成目标文件。

CodeBye 版权所有丨如未注明 , 均为原创丨本网站采用BY-NC-SA协议进行授权 , 转载请注明关于C++头文件重复包含的问题
喜欢 (0)
[1034331897@qq.com]
分享 (0)

文章评论已关闭!