只是为了看它是否可行(我知道它的形式很糟糕),我在头文件中完全定义了一个函数,并在主cpp文件中为所述函数做了相应的前向声明。 C ++函数不需要在它们使用的转换单元中定义,因此为什么头文件几乎完全只是前向声明(内联函数除外)。但是,当我试图编译这个项目时,它说有一些未解决的外部因素。
当我将头文件的全部内容移动到源文件中时(也删除头文件),它编译得很好并按预期执行。那么,在构建项目时是不是编译了头文件,还是只有一些我不了解的例外?
此外,即使我只是转到属性资源管理器中的头文件属性并将其File Type
设置为C/C++ Code
并将其扩展名更改为.cpp,它仍然会赢得&#39 ; t编译(即使它会删除它并创建一个新的源文件,我认为这是最奇怪的部分)。
(我正在使用已停用的扩展程序/Za
,如果这会改变任何内容)
这是代码文件
//main.cpp
void foo();
void main()
{
foo();
}
和头文件
//test.h
#include <iostream>
void foo()
{
std::cout << 'a';
}
答案 0 :(得分:4)
头文件由预处理器包含在编译单元 - cpp
文件中。之后只有编译器编译cpp
文件中的源代码。
将函数定义放入标题.h
文件中时。您不将此头文件包含到main.cpp
中,并且编译器不会编译它,因为预处理器不会将其包含在main.cpp
中。
您可以自己查看预处理器作业的结果。在Visual Studio中,使用Preprocessor属性页上的/P
选项。对于main.cpp
,输出将位于main.i
。
答案 1 :(得分:1)
头文件不是自己编译的,只是想象一下文本实际上在包含它的.cpp文件中。这个新的'merged'文件是编译的。因此,您可以将函数放在头文件中,并在将其包含在.cpp文件中时进行编译。
它不好的原因是,如果你将它包含在第二个.cpp文件中,它将尝试再次编译,你将遇到问题。
答案 2 :(得分:1)
标题中函数定义的问题并不是它们被跳过。真正的风险是他们被编译了两次,这曾经太多了。 C ++有一个称为单一定义规则的东西,你通过两次编译单个函数来违反该规则。
有一个重要的例外:inline
函数可以免除,并且可以在每个翻译单元中定义。