C++ 多声明vs未定义
我试图从一个文件中导入变量,该文件在另一个文件中的类中使用,并最终将其导入另一个文件并编译 让我来说明问题的重现情况: arrayFile.hppC++ 多声明vs未定义,c++,c++11,C++,C++11,我试图从一个文件中导入变量,该文件在另一个文件中的类中使用,并最终将其导入另一个文件并编译 让我来说明问题的重现情况: arrayFile.hpp int arr[] = { 1,2,6,5,4,3 }; classFile.hpp #include <iostream> using namespace std; #include "arrayFile.hpp" class MyClass{ private: int v1; public: MyCl
int arr[] = {
1,2,6,5,4,3
};
classFile.hpp
#include <iostream>
using namespace std;
#include "arrayFile.hpp"
class MyClass{
private:
int v1;
public:
MyClass();
void setV(int v);
int getV();
int funcM();
};
如果我这样做:
In file included from mainfile.cpp:5:0:
classFolder/arrayFile.hpp:1:9: error: redefinition of ‘int arr []’
int arr[] = {
^
In file included from classFolder/classFile.hpp:3:0,
from mainfile.cpp:4:
classFolder/arrayFile.hpp:1:5: note: ‘int arr [6]’ previously defined here
int arr[] = {
^
我已经能够让编译器告诉我arr[]也没有定义,但是我无法重现这个错误
我做错了什么
我面临的真正问题需要我将数组和结构导入到一个类中,这个类被导入到另一个更大的类中,最后一个类最终被main使用。这是我复制它的最好方法。我不知道如何解决这个问题。您不应该在classFile.hpp中包含arrayFile.hpp。仅将其包含在classFile.cpp中。另外,在mainfile.cpp中,在主函数之前添加行
extern int arr[];
这一行告诉编译器称为arr的int类型数组将在与mainfile.cpp链接在一起的其他cpp文件中定义
按如下方式编译程序:
g++ -std=c++11 -c main.cpp classFile.cpp
g++ -std=c++11 main.o classFile.o
./a.out
第一行分别编译文件,创建main.o和classFile.o文件
第二行将它们链接在一起,创建一个可执行文件a.out
第三行运行可执行文件
由于添加新文件使编译过程变得复杂,我建议使用Makefile。您不应该在classFile.hpp中包含arrayFile.hpp。仅将其包含在classFile.cpp中。另外,在mainfile.cpp中,在主函数之前添加行
extern int arr[];
这一行告诉编译器称为arr的int类型数组将在与mainfile.cpp链接在一起的其他cpp文件中定义
按如下方式编译程序:
g++ -std=c++11 -c main.cpp classFile.cpp
g++ -std=c++11 main.o classFile.o
./a.out
第一行分别编译文件,创建main.o和classFile.o文件
第二行将它们链接在一起,创建一个可执行文件a.out
第三行运行可执行文件
由于添加新文件使编译过程变得复杂,我建议使用Makefile。广义上讲,在头文件中定义变量不是一个好主意-假设所述头文件将由多个源文件包含 编译项目时,预处理器通过将包含的头文件的内容放入包含它的文件中来处理include语句。 例如: 这是一种简化,但足以说明问题。 那么在你的例子中发生了什么? arrayFile.hpp包含在classFile.hpp中,classFile.hpp包含在classFile.cpp和mainfile.cpp中。考虑包含树:可能是有帮助的。
arrayFile.hpp
|
classFile.hpp
/ \
classFile.cpp mainfile.cpp
想一想我说的:用包含的文件内容替换包含,看看我说classFile.cpp和mainfile.cpp都以arr数组的定义结束时,您是否不同意
在编译项目时,接下来会发生什么?编译器将源代码(特别是预处理器输出)编译为对象文件。例如,预处理的classFile.cpp变成classFile.o,预处理的mainfile.cpp变成mainfile.o
最后,将对象文件或它们归档到的库链接起来,形成可执行文件
当链接器尝试链接classFile.o和mainfile.o时,它会发现两者都定义了arr。因此,您得到的是多定义链接器错误,而不是编译器错误
因此:如果一个头文件被多个源文件直接或间接包含,那么如果头文件定义了变量,您将遇到链接器错误。这就是为什么,在头文件中声明变量并在一个源文件中定义它们是标准做法
希望这会有所帮助。一般来说,在头文件中定义变量不是一个好主意-假设所述头文件将包含在多个源文件中 编译项目时,预处理器通过将包含的头文件的内容放入包含它的文件中来处理include语句。 例如: 这是一种简化,但足以说明问题。 那么在你的例子中发生了什么? arrayFile.hpp包含在classFile.hpp中,classFile.hpp包含在classFile.cpp和mainfile.cpp中。考虑包含树:可能是有帮助的。
arrayFile.hpp
|
classFile.hpp
/ \
classFile.cpp mainfile.cpp
想一想我说的:用包含的文件内容替换包含,看看我说classFile.cpp和mainfile.cpp都以arr数组的定义结束时,您是否不同意
在编译项目时,接下来会发生什么?编译器将源代码(特别是预处理器输出)编译为对象文件。例如,预处理的classFile.cpp变成classFile.o,预处理的mainfile.cpp变成mainfile.o
最后,将对象文件或它们归档到的库链接起来,形成可执行文件
当链接器尝试链接classFile.o和mainfile.o时,它会发现两者都定义了arr。这样就得到了多定义链接器
错误-不是编译器错误
因此:如果一个头文件被多个源文件直接或间接包含,那么如果头文件定义了变量,您将遇到链接器错误。这就是为什么,在头文件中声明变量并在一个源文件中定义它们是标准做法
希望这能有所帮助。始终标记主语言,并改进以下问题:我应该如何在终端中使用g++-std=c++11编译所有语言?只需列出所有.cpp文件,您就可以得到问题的答案。但是,如果你不这样做,那么考虑编写A来说明你的主要观点。ARR不应该在页眉中定义。我怀疑是否应该避免使用全局变量。我假设您不允许使用std::array或std::vector?虽然您确实标记了c++11,但也始终标记了主语言,在这个问题上有所改进,我应该如何在终端中使用g++-std=c++11来编译它呢?只需列出所有.cpp文件,您就可以得到问题的答案。但是,如果你不这样做,那么考虑编写A来说明你的主要观点。ARR不应该在页眉中定义。我怀疑是否应该避免使用全局变量。我假设您不允许使用std::array或std::vector?虽然您标记了c++11
// main.cpp
#include "foo.h"
int main( int argc, char* argv[] )
{
return 0;
}
// preprocessor output
typedef int myInt;
int main( int argc, char* argv[] )
{
return 0;
}
arrayFile.hpp
|
classFile.hpp
/ \
classFile.cpp mainfile.cpp