我的头文件是这样的:
//Sales_data.h
#ifndef SALES_DATA_H
#define SALES_DATA_H
//#include<string>
struct Sales_data
{
std::string bookNo; //compiles without error
};
#endif
通常,每当我们必须在代码中使用字符串变量时,我们都会包含string
标头。但是使用上面标题的程序编译没有任何错误,即使我没有在程序中包含string
标题。
答案 0 :(得分:2)
这是标准库的特定编译器/实现的功能。一般来说,为了使您的代码100%可移植,您应该包含string
标头,因为不是每个编译器都会这样做。我知道gcc
和clang
的当前版本允许它(我不确定MSVC),但为了使您的代码符合标准,您应该始终包含string
标题,您要使用std::string
。如果您发现自己必须为编译器不执行此操作的平台进行开发,则上面给出的代码将无法编译,您将不得不花费时间和精力进行调试。那为什么要这么麻烦?折腾#include <string>
,继续编程,省去以后修复它的麻烦。
答案 1 :(得分:1)
include
语句有效地将包含文件的内容粘贴到包含文件中。这构建了一个组合源文件和所有包含头的大型文件。这个组合文件最终是编译的。
让我们在标题中添加一个简单的驱动程序来演示它是如何工作的:
#include <string>
#include "sales_data.h"
int main()
{
}
变为
#include <string> // actual contents of string omitted for brevity
#ifndef SALES_DATA_H
#define SALES_DATA_H
//#include<string>
struct Sales_data
{
std::string bookNo; //compiles without error
};
#endif
int main()
{
}
这将编译,但它依赖于外部依赖:<string>
必须包含在"sales_data.h"
之前。这意味着一点点改变
#include "sales_data.h"
#include <string>
int main()
{
}
你的鹅煮熟了。更糟糕的是,或许
#include <iostream>
#include "sales_data.h"
int main()
{
}
编译得很好,因为<iostream>
在编译器X的标准库实现下包含<string>
。也许编译器Y的库没有并产生错误消息,说std::string
缺失。更糟糕的是,编译器Z的设计者认为通过向前声明std::string
而不是包括<string>
可以获得可衡量的优化,并且前向声明不足以完全满足"sales_data.h"
。编译器Z可能会抛出一个完全奇怪的错误消息,因为std::string
存在,但不完整,不能用于声明bookNo
。
此标头的包含者必须提前知道必须包含<string>
或者只是为了编译代码而面临一些恼人的调试。这对任何人都没有公平的期望,特别是当解决方案如此完全无关紧要时。
因此,约定和最佳实践是确保所有标头在内部都是自洽的。标题应该能够独立并使用最小的驱动程序进行编译。如果以下内容无法编译
#include "header_under_test.h"
int main()
{
}
"header_under_test.h"
未完成且应该在暴露于野外之前完成。你节省的时间和挫折可能是你自己的。