记录一个让笔者有点无语的语法错误 debug 过程...
1.晚上使用 VScode 写代码,编译时出现如下报错信息 "error: ‘ostream’ has not been declared".编译无法通过.
error: ‘ostream’ has not been declared // ostream 未声明
2.产生上述报错时,源文件中包含了头文件 iostream.笔者第一反应,是和 C 语言下出现类似报错时一样,认为可能没有包含对应声明了 ostream 类型的头文件.比如 C 语言中,如果没有包含头文件 stdio.h,则在源文件中使用 printf 同样会产生 'printf' has not been declared 的报错.所以笔者怀疑头文件 iostream 中没有包含对 ostream 的声明( 虽然这个怀疑笔者也觉得有点奇怪... ).
3.使用 VScode 进行代码编辑时,可以通过选中某个头文件,右键 -> 转至定义( go to definition )/查看定义( peek definition ) 查看头文件的内容.所以笔者直接就想看看头文件 iostream 中是否包含所想要的 ostream 声明.于是进入头文件 iostream,发现该头文件开始位置包含了头文件 ostream...内心 os : 这个头文件 ostream 怎么看也应该包含有类型 ostream 的声明啊...要不为啥叫这名...
4.觉得头文件 ostream 中应该包含有 ostream 的类型声明,所以包含头文件 iostream => 包含头文件 ostream => 包含有 ostream 类型声明,那么使用 ostream 应该是可以的.所以再编译一次程序.结果继续,"error: ‘ostream’ has not been declared".有点抓狂.
5.于是怀疑,难道头文件 ostream 中都不包含有 ostream 的类型声明???所以首先,打开了 ostream 的内容,发现其中主要定义的是一个叫做 basic_ostream 的类模版,直接搜索 ostream 关键词不好定位 ostream.于是一怒之下,打开了 cplusplus-ostream ,查看头文件 ostream 的介绍,发现其中确实是有类 ostream 的.
继续进入查看类 ostream 的说明( class std::ostream ),发现 ostream 的定义如下,所以直接在头文件 ostream 中搜索该定义,结果查找不到...内心 os : 这是个什么鬼...页面上说有,头文件里面没有?
typedef basic_ostream<char> ostream; // ostream 的定义
6. ostream 的声明到底在哪里?笔者觉得不能放弃.于是想到,输出流 cout 就是 ostream 类型的,其在头文件 iostream 中有声明如下,其中用到了类型 ostream.
extern ostream cout; //头文件 iostream 中对 cout 的声明
直接选中 ostream,然后右键 -> 转到定义,跳转到 ostream 的定义,发现其位于头文件 iosfwd 中,且形式与前面页面介绍的 ostream 定义相同.根据头文件 isofwd 的介绍,该头文件包含的是一些与 io 有关的前向声明.
此时笔者心中对于 ostream 出现的位置还是有点诧异,为啥会出现在这里呢?这跟 cplusplus 网站上介绍的不太一样啊...同时,笔者在/查看头文件定义的过程中如 iostream 时,发现 VScode 会报告系统上存在两个对应头文件,比如笔者 Ubuntu 环境下,系统头文件位置在 /usr/include/c++/ 目录下,而其中包含有 5.5.0/7.5.0 的头文件版本.此时笔者甚至开始怀疑,难道是因为头文件版本的改变使得 ostream 定义的位置发生了改变?脑洞逐渐变大...
7.既然找到了 ostream 的声明,那么笔者最直接的思路,就是在源文件中直接包含头文件 iosfwd,再进行编译.结果仍然"error: ‘ostream’ has not been declared".这就很让人郁闷了???到底是因为啥?
8.于是笔者最后,做了一个本来之前就应该做的事情--google.输入关键词 error: ‘ostream’ has not been declared.返回的搜索条目中第一条是 stackoverflow 的一个问题 istream and ostream problem - C++,其第一个答案说,请确保在使用 ostream 前加入对应的命名空间的声明.........然后笔者就听话的在源文件中加入了命名空间声明,然后就编译通过了..........
using std::ostream; //声明
9.那么为什么只需要包含头文件 iostream 就包含了对类型 ostream 的声明呢,而且貌似 ostream 文件中还不含有 ostream 的声明?其实原因是,头文件 iostream 包含了头文件 ostream => 头文件 ostream 包含了头文件 ios => 头文件 ios 包含了头文件 iosfwd => 头文件 iosfwd 就包含了 ostream 的声明...所以就齐活了...istream 的情况与 ostream 类似.
emmmmm,所以说,有时候遇到这种编译问题,思路是需要活跃一点,但有时候, google 一下可能就直接解决了...