在线时间:8:00-16:00
迪恩网络APP
随时随地掌握行业动态
扫描二维码
关注迪恩网络微信公众号
我总结的类型重定义情况有三。 一、没有在文件头加#pragma once指示符。 Type1.h: //#pragma onceMain.cpp: #include "Type1.h"#pragma once的作用是保证本文件只被编译一次,如果没有在Type1.h中加这句话,那么在main.cpp里面包含了两次Type1.h, 就相当于在main.cpp里面定义了两次Type类, 自然就是类型重定义了。 二、两个不同的头文件中定义了相同的类型(均有#pragma once) Type1.h: #pragma onceType2.h: #pragma onceMain.cpp: #include "Type1.h"这里main.cpp中同时包含了Type1.h, Type2.h两个头文件, 虽然其文件头都有#pragma once,但因为是不同的文件, 预编译器还是会两次把Type类的定义放在Main.cpp中, 所以也会出现了重定义。 三、从两个不同的路径包含了同一个头文件 前面两种是比较常见, 也是比较容易解决的情况, 而这里要讲的第三种情况, 比较少见, 而且一般出现在有虚拟映射盘的时候。(这样才能做到从两个不同的路径包含同一个头文件), 其他会在什么时候出现, 我还没想到, 知道的朋友顶一下:)。下面我来分析一下: 1) 有VC工程在D:\Test目录下。 2) 映射虚拟盘X为D:\Test. 不熟悉的网友可以按此操作: 开始->运行->在运行窗口输入:cmd->在cmd窗口输入: Subst X: D:\Test 3) 该工程有文件Type1.h, main.cpp Type1.h: #pragma onceMain.cpp: #include "Type1.h"这里我们在main.cpp这样包含了两个头文件, 从本质上来讲, 它们都对应于物理盘D:\Test下的文件Type1.h, 是同一个文件。但在不同的操作下, VC对其有不同的解释。#include "X:\Type1.h"用的是绝对路径, 自然没有什么异议, 但#include "Type1.h"却有些变化:
4) 在D:\Test下打开工程, 编译, 出现类型Type重复定义错误 这种情况下,main.cpp预编译为: Main.cpp: #include "D:\Test\Type1.h"#pragma once只保证本文件被编译一次, 这里VC将其认为是两个不同的文件, 所以都要编译, 出现编译错误自然也就不奇怪了。 当然, 这里如果从X:\ 下打开工程的话,VC就会认为都是从X:\Type1.h下包含这个文件,#pragma once起到了作用, 也就不会出现类型重定义了 四、总结 我在VC7, VC8,和Dev C++中都测试了第三种情况, 发现只有Dev C++是可以通过编译的。这可能是微软VC的#pragma once还不够智能吧,轻易的被Windows的虚拟盘给蒙蔽了双眼, 看不到其本质(只是猜测, 或许VC这么处理是有其他用意的)。 因为在稍大一点的工程开发中, 我们一般都会用虚拟盘来方便工作, 一是访问快捷,简化了路径, 二是因为多人协同开发,我们一般希望大家源代码路径相同,但我们不应强制要求大家都把源代码放死在某一目录下, 这时把你放源代码的路径映射为一个虚拟盘(比如说统一为X:)就能把大家的代码路径统一起来了。但是另一方面,有了虚拟盘, 就为出现类型重定义提供了条件, 以下是我得出的两个解决方法: 1) 抛弃#pragma once使用古老但集稳定性与移植性于一身的 #ifndef _XXX_H来保证头文件只被编译一次。这样不管是包含两个相同的文件,还是包含两个不同的文件,或是包含两个文件相同但路径不同的文件, 只要_XXX_H被定义过, 就不会再编译那个编译(但这里我们要保证_XXX_H的唯一性, 如果两个不同的头文件里用了同一_XXX_H,是会出问题的) 2) 在包含头文件时,不要使用绝对路径, 哪怕那是虚拟盘的绝对路径。
(搬自以前blog, 2007-08-26)
|
2023-10-27
2022-08-15
2022-08-17
2022-09-23
2022-08-13
请发表评论