我对C和编译过程的基本知识最近变得生疏.我试图找出以下问题的答案,但我无法连接编译,链接和预处理阶段基础知识.快速搜索谷歌也没什么帮助.所以,我决定来到最终的知识来源:)
我知道:不应该在.h文件中定义变量.可以在那里宣布它们.
原因:因为头文件可能包含在多个位置,因此重新定义变量多次(链接器给出错误).
可能的解决方法:在头文件中使用header-guard并在其中定义变量.
它真的是一个解决方案:不.因为标题保护是用于预处理阶段.那就是告诉编译器这部分已经包含在内并且不再包含它.但是我们的多重定义错误来自链接器部分 - 在编译之后很久.
整件事让我对预处理和链接的工作方式感到困惑.如果已经定义了头部保护符号,我认为预处理将不包括代码.在那种情况下,不应该解决变量问题的多重定义吗?
这些预处理指令会在标题保护下重新定义编码过程,但是链接器仍会获得符号的多个定义,会发生什么?
在 C 和 C++ 中,不能有一个具有两个定义的函数。例如,假设我们有以下两个文件:
1.c:
int main(){ return 0}
Run Code Online (Sandbox Code Playgroud)
2.c:
int main(){ return 0}
Run Code Online (Sandbox Code Playgroud)
发出命令gcc 1.c 2.c会给你一个duplicate symbol链接器错误。为什么结构和类不会发生同样的情况?为什么我们允许对同一个结构有多个定义,只要它们具有相同的标记?
免责声明:这可能是一个基本问题,但我是一名理论物理学家,通过训练试图学习正确编码,所以请耐心等待。
假设我想模拟一个相当复杂的物理系统。在我的理解中,对这个系统建模的一种方法是将它作为一个类来介绍。但是,由于涉及系统,类会很大,可能有很多数据成员、成员函数和子类。将主程序和这个类放在一个文件中会非常混乱,所以为了更好地概述项目,我倾向于将这个类放在一个单独的 .h 文件中。这样我就会有类似的东西:
//main.cpp
#include "tmp.h"
int main()
{
myclass aclass;
aclass.myfunction();
return 0;
}
Run Code Online (Sandbox Code Playgroud)
和
// tmp.h
class myclass
{
// data members
double foo;
double bar;
public:
// function members
double myfunction();
};
double myclass::myfunction()
{
return foo + bar;
}
Run Code Online (Sandbox Code Playgroud)
然而,这相当于我的新编译器中的以下编译器警告:function definitions in header files can lead to ODR violations. 那么我的问题是:处理这种情况的首选方式是什么?我想我可以将 tmp.h 变成 tmp.cpp,但据我所知,这是 .h 文件的预期用途?
根据一个定义规则,类和结构定义不得在单个翻译单元中重复。
但是,为什么这样的话,如果它们实际上是定义,则允许以多个翻译单元重复它们。在这种情况下,链接器为什么不引发多定义错误?
例如-以下操作应通过相同的逻辑引发多个定义错误
测试
#ifndef TEST
#define TEST
class s {
int a;
int b;
};
#endif
Run Code Online (Sandbox Code Playgroud)
test1.cpp
#include "test.h"
int main() {}
Run Code Online (Sandbox Code Playgroud)
test2.cpp
#include "test.h"
Run Code Online (Sandbox Code Playgroud) c ×3
c++ ×3
c++-faq ×1
declaration ×1
definition ×1
header-files ×1
hfile ×1
linker ×1
terminology ×1