在C++头文件中声明变量

28

我试图使用良好的编程实践创建一个简单的程序,在C++中从用户获取输入。它由Input.hpp、Input.cpp和main.cpp组成。即使我使用了ifndef来防止多次定义,但我仍然遇到了多重定义错误。

Input.hpp

#ifndef Input_HPP
#define Input_HPP

#include <string>
#include <vector>
using namespace std;

vector<string> Get_Input();
vector<string> input_array;
string starting_position;
int input_number;

#endif

输入.cpp

#include <iostream>
#include <cmath>
#include <string>
#include <vector>

#include "Input.hpp"

using namespace std;

vector<string> Get_Input()
{
    cin>>starting_position;
    cin>>input_number;
    for (int i = 0; i < input_number; i++)
    {
        cin>>input_array[i]; 
    }
    cout<<"Done";

    return input_array;
}

主程序.cpp

#include "Input.hpp"
#include <iostream>
using namespace std;

int main()
{

    Get_Input();
    return 0;
}

当我从头文件中删除变量声明并将它们放在cpp文件中,但保留函数声明在头文件中时,程序会没有错误地编译。我理解变量和函数都可以在头文件中声明,请问有人能向我解释一下我缺失了什么吗?

谢谢。

2个回答

46

头文件并不聪明,它只是告诉预处理器将整个头文件放在include行的位置。

如果这样做,你会发现变量被声明了两次。

为了解决这个问题,你应该在其中一个cpp文件中声明变量,并在头文件中使用extern

比如在input.cpp中:

int input_number;

并且在input.hpp文件中:

extern int input_number;

2
这就是变量的前向声明方法。更多关于extern关键字的内容请参见6.7-外部链接和变量前向声明 - Enes

8
包含保护只能防止在已经复制了包含文件的情况下进行复制,这在您的代码中是有效的,编译器可以成功编译代码。现在您遇到的是链接器错误,在编译器生成Input.cppmain.cpp的目标文件后,它会发现两个具有相同名称的符号-变量,并开始抱怨应该使用哪一个?
因此,总结一下,当您在头文件中定义变量时,请添加extern关键字以使链接器满意。

抱歉,哪两个符号的名称相同?如果包含保护防止在两个文件中复制“input_number”,那么该变量只会有一个声明存在吧? - Hans GD
@HansGD,迟到总比不到好。这两个.cpp文件是独立编译的,甚至可能由不同的代码作者编写。包含保护阻止您在每个文件中多次包含相同的头文件。然而,预处理器对每个文件都是从头开始的,所以包含保护对于不同的.cpp文件是无效的。每个文件最终都会得到在头文件中定义的符号。最后一步是将这两个生成的目标文件链接在一起,此时链接器会看到每个变量的两个定义。大致上,声明不拥有数据,但定义拥有数据。 - undefined

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接