我有“Hello World”代码,它使用来自另一个拥有它标题的hi.cpp文件的函数fhi。
如果我的理解错误,请纠正我:
我可以包含像#include "c:\c\hi.cpp"
这样的cpp文件,而不是使用标头而没有任何问题,除了它在头文件中看起来更具可读性。
如果我在主程序hi.h
中包含类似标题的标题,则必须hi.h
包含hi.cpp
,或者根据相同的文件名hi
自动完成。我想知道编译器如何知道函数fhi
正在哪里。
是否可以为header和cpp文件使用不同的名称?
PROGRAMM:
#include "stdafx.h"
#include "c:\c\hi.h"
int _tmain(int argc, _TCHAR* argv[])
{
fhi(1);
return 0;
}
hi.h
#include <cstdlib>
#include <iostream>
int var;
int fhi(int f);
hi.cpp
#include <cstdlib>
#include <iostream>
int fhi(int f)
{
return 0;
}
答案 0 :(得分:2)
必须hi.h包括hi.cpp
没有。 hi.h
仅包含声明,可以是其他.cpp文件的其他声明。
我想知道编译器如何知道函数fhi的位置。
没有。您需要将所有* .cpp文件编译到目标文件中。在您的情况下,您将有两个目标文件:program.o
和hi.o
。链接器现在可以获取这两个目标文件,并吐出可执行文件。在这个阶段解决了对其他函数的引用(在这种情况下是fhi(..)的实际定义)。
另外,为什么在#includes中使用绝对路径?当您移动“c”目录时它会中断。
答案 1 :(得分:2)
通常情况下,构建系统会将.cpp
文件编译为目标文件,然后用于构建主可执行文件。告诉构建系统的方法差别很大。
重要的一点是,您的hi.cpp
必须包含hi.h
。您还应在hi.h
中添加include guard,以便在翻译单元中多次包含一次。
答案 2 :(得分:2)
我可以包含cpp文件,如#include“c:\ c \ hi.cpp”而不是使用 标题没有任何问题,除了它看起来更多的事实 在头文件中可读。
是的,你可以这样做,但不推荐,其中一个问题是封装;你没有隐藏实现细节。你提到的可读性也是一个问题,标题更容易阅读,因为它清楚地显示了哪些方法是公开的。
如果我在主程序hi.h中包含类似标题的标题,则必须为hi.h 包括hi.cpp,或者它是根据同一文件自动完成的 嗨。我想知道编译器如何知道函数fhi的位置。
标头需要显式包含在hi.cpp和任何使用标头中定义的类的.cpp文件中。
是否可以为header和cpp文件使用不同的名称?
是的,但不建议这样做,这使得查找更加困难。
作为一般规则:考虑其他程序员可能希望查看您的代码,因此您需要对其进行构建,以便易于阅读和理解,并使您在2年后更容易记住事情就是这样。
答案 3 :(得分:2)
在Visual Studio中,将编译项目中包含的所有CPP文件以生成OBJ文件。这些OBJ文件将链接在一起形成EXE或DLL。
包含文件类似于粘贴该位置的文件内容。唯一的区别是这种粘贴是在编译期间由预编译器完成的。
查找函数体所在的位置由编译器完成,如果函数是内联函数,或者是在创建最终二进制文件时由链接器完成。
答案 4 :(得分:2)
首先,如果头文件与包含它的源文件位于同一目录中,则只能使用
#include "hi.h"
换句话说,您不必使用完整路径。 (例如,参见"stdafx.h"
。)
其次,在头文件中,您不需要包含其他头文件,除非您需要其中的类型。在您的头文件中,您没有包含所需的任何内容。
第三,你应该保护头文件头文件不被多次包含在同一个源文件中,这可以用一个所谓的include guard完成,在某些编译器中通过一个名为{{3的特殊指令来启动}}
第四,在您的头文件中,您定义全局变量var
。然后,将在包含头文件的每个源文件中定义此变量,这将导致错误。您需要将变量声明为extern
:
extern int var;
然后在一个源文件中,您就像现在一样定义变量。
第五,你永远不应该在头文件中包含源文件(有一些你不必考虑的特殊例外)。相反,您将所有源文件添加到项目中(我假设您在MS VisualStudio中)并且它们将自动构建并链接在一起。
第六,既然您似乎使用的是VisualC ++,那么您可能正在使用名为#pragma once
的东西。这是编译器用来加速编译的东西。但是,要使其工作,您必须在所有源文件中包含"stdafx.h"
。这包括实际上必须是每个源文件中的第一个非注释行。