快速提问。
我正在努力让C ++失效,今天我花了好几个小时的双定义链接器错误(“这已经被定义了!”)我终于意识到这是因为我有这样的布局:
的main.cpp
#include Dog.cpp
Dog.cpp
#include Dog.h
Dog.h
// (Dog class and prototype of test function)
现在我通过在main.cpp中包含Dog.h而不是Dog.cpp来清除它。
通过包含.h文件,具有相同前缀的.cpp文件是否可以用程序编译?
当程序只包含.h并且没有任何对Dog.cpp的引用时,我感到震惊。我花了很多年的谷歌搜索,但没有答案真的帮助我理解发生了什么。
编辑:我忘了添加我在.h中的原型,并在.cpp中定义了该类的函数,这就是给我“已定义”错误的原因。
答案 0 :(得分:7)
通过包含.h文件,具有相同前缀的.cpp文件是否可以用程序编译?当程序只包含.h并且没有任何对Dog.cpp的引用时,我感到震惊。
没有
您的计划分阶段建立。
对于编译阶段,每个翻译单元只需要声明(大致相当于单个.cpp文件,其中#include
已解决)。声明甚至首先存在的原因是作为一种“承诺”,以后可以找到完整的函数定义。
g++ -c Dog.cpp # produces `Dog.o`
g++ -c main.cpp # produces `main.o`
对于链接阶段,在翻译单元之间解析符号。您必须将编译Dog.cpp和编译main.cpp的结果链接在一起(也许您的IDE正在为您执行此操作?),此链接进程会在它们之间找到所有正确的函数定义以生成最终的可执行文件。
g++ Dog.o main.o -o program # produces executable `program`
(要不然,或者你实际上还没有进入链接阶段,只有一个目标文件(Dog.o);你不能执行它,部分原因是因为它没有所有的函数定义英寸)
这两个阶段可以同时完成,使用“速记”:
g++ Dog.cpp main.cpp -o program # compiles, links and produces executable
答案 1 :(得分:0)
包含不会自动导致编译,没有。
实际上,实际编译器根本看不到#include
语句。它被较早的步骤(称为预处理器)删除。
如果您从未编译Dog.cpp
文件,我不确定它是如何构建的。您是否使用该文件中定义的代码引用了任何对象?
答案 2 :(得分:0)
不,.cpp文件不会自动编译。您可以手动执行此操作,创建生成文件,也可以使用在同一项目中同时具有这两者的IDE。
答案 3 :(得分:0)
您没有指定编译方式。如果您正在使用IDE并自动为项目添加.h和.cpp,那么它将自动编译和链接。
使可执行文件运行有两个阶段:编译和链接。编译是代码被解释并转换为较低级代码的地方。链接是您使用的所有功能得到解决的地方。这是您遇到重复功能错误的地方。