C++ 利用条件编译来避免重复引用为什么需要手写?编译器不能自动做这件事情吗?

2022-03-25 13:33:13 +08:00
 vcfghtyjc

继续读《 C++ Primer 》,看到 2.6 中介绍了利用条件编译来避免重复引用。以下是源码:

#ifndef SALES_DATA_H
#define SALES_DATA_H
#include <string>
struct Sales_data {
  std::string bookNo;
  unsigned units_sold = 0;
  double revenue = 0.0;
};
#endif

所以理论上来说,是不是每个自定义的数据结构都应该加上这个判断,从而避免重复引用?为什么编译器不能自动做这个事情?重复引用会带来什么样的问题?

3334 次点击
所在节点    C++
29 条回复
masterclock
2022-03-25 14:31:02 +08:00
@vcfghtyjc 引用两次的情况存在啊
见过一些代码,define 个东西,include 一个文件,然后 define 另一个东西,再一次 include ,这样就能包含进来不一样的东西了
codehz
2022-03-25 14:31:49 +08:00
多次 include 是有意义的( c 里用的比较多)
可以起到类似代码生成的作用
你可以在某个文件里放一堆类似 GEN(a, int, "some text")的“语句”,然后在不同的地方 include 的时候定义 GEN 宏展开成不同的东西(比如一边展开成 enum ,另一边展开成 switch case ,就可以实现 enum 值打印)
C++显然没必要打破这种兼容性,自然就保留下来了
3dwelcome
2022-03-25 15:06:59 +08:00
@vcfghtyjc "那能不能编译前自动给每个 data structure 都加个判断,除非声明就是要重复引用?"

因为做不到啊。C 编译器的宏预处理和实体编译模块是分两步进行的。

也就是#include 会忠实执行内联文件的责任,先把所有头文件都塞到一个巨大的临时 C 文件里,再给编译器。

编译器在编译时候,仅仅从临时 C 文件里看,看不出 data structure 定义是不是来自同一个头文件。如果知道,那肯定是能自动去重复的。

同样是编译程序,这点还是 java 设计好。C 有太多历史负担了。
ysc3839
2022-03-25 16:10:00 +08:00
@3dwelcome 从标准看是不可以,但是主流实现都支持 #pragma once 了,实际是可以
msg7086
2022-03-25 17:35:23 +08:00
头文件在设计的时候就是做成像复制粘贴一样引入源码文件里的。
比如你头文件里写一个 printf 语句,然后在函数里每次#include 这个头文件就相当于把这个 printf 语句复制粘贴到代码里一样,你引用 3 次就等于复制粘贴了 3 次语句进来。
因为头文件本来实现的就是复制粘贴功能,所以很难直接处理语言本身的含义。

简单来说就是 Ctrl-V 这个功能为什么要的管你 Ctrl-V 了几次呢。

再举一个现实中会用到的例子。比如你写了一个头文件,封装在一个命名空间里,然后把命名空间做成宏。
那么你就可以用类似:
#define NS ns1
#include <code.h>
#undef NS
#define NS ns2
#include <code.h>
#undef NS
这样前后生成两个不同命名空间的两套代码。
x265 就是用类似的方法把 8bit 10bit 12bit 的编码器分别装在三个命名空间里然后链接在一起的。
ligiggy
2022-03-26 10:02:51 +08:00
c++永远都这么有意思, full of fun 。
seakingii
2022-03-26 11:14:36 +08:00
最讨厌 C,C++的头文件啥的

C,C++的编译问题很多,所以新一点的语言,比如 RUST, GOLANG 都有一部分责任要解决 C,C++编译的问题
troywinter
2022-03-26 13:21:46 +08:00
你说的这玩意有两个实现,一个叫 java ,一个叫 c#,直接用就行了
fawdlstty
2022-04-23 22:07:03 +08:00
@vcfghtyjc 真有可能引用两次并且以不同方式引用。参见里面我备注的 xmh 大佬的答案
https://www.zhihu.com/question/456804478
作为头文件引用一次,可以调用里面的函数;作为字符串引用一次,可以做字符串处理

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/842838

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX