外部变量导致多重定义错误

Posted

技术标签:

【中文标题】外部变量导致多重定义错误【英文标题】:extern variable causes multiple definition error 【发布时间】:2013-01-26 06:36:10 【问题描述】:

我一直在尝试使用 extern 来使用之前定义的变量。

我以前没有使用过 extern,现在我需要使用它来定义一次变量并在多个文件中使用它们

我已经为这个问题编写了最小化版本的代码。我有四个文件

lib.h

#ifndef LIB_H
#define LIB_H

#include <iostream>

namespace lib 

  extern bool initialized;

  bool initialized = false;

  static void isInit(char* parent) 
    std::cout << "Library for [" << parent << "] initialized? " << (::lib::initialized ? "yes" : "no") << "\n";
  
 // namespace lib
#endif

vehicle.h

#ifndef _VEHICLE_H
#define _VEHICLE_H
#include <string>

class Vehicle 
  public:
    Vehicle(const std::string& manufacturer,
            const std::string& model,
            int year);
    std::string manufacturer;
    std::string model;
    int year; 
;
#endif

以下是名为vehicle.cpp的vehicle.h文件的实现

#include "vehicle.h"

#include "lib.h"

Vehicle::Vehicle(const std::string& manufacturer,
                 const std::string& model,
                 int year) :
                    manufacturer(manufacturer),
                    model(model),
                    year(year) 
   ::lib::isInit("Vehicle");

main.cpp

#include "vehicle.h"

#include "lib.h"

int main(int argc, char** argv) 

   ::lib::isInit("main");

   ::lib::initialized = true;

   ::lib::isInit("main");

   Vehicle vehicle("Toyota", "Corolla", 2013);

   return 0;

我正在使用 g++

g++ -Wno-write-strings main.cpp vehicle.cpp -o bin/main.cpp.bin 

我收到以下错误:

/tmp/cclVpsgT.o:(.bss+0x0): multiple definition of `lib::initialized'
/tmp/ccmJKImL.o:(.bss+0x0): first defined here
collect2: error: ld returned 1 exit status

我检查了以下输出:

g++ -Wno-write-strings main.cpp vehicle.cpp -E

每次包含 lib.h 时都会发生多个定义。

我的问题是:

当有定义保护时,为什么会多次包含 lib.h 我将如何定义'extern'变量并在同一个文件中初始化它(因为它稍后会在同一个文件中使用)

【问题讨论】:

【参考方案1】:

当有定义保护时,为什么lib.h 包含多次

你需要删除定义:

bool initialized = false;

并将其放在一个且只有一个源文件中。

包含保护防止同一个头文件多次包含在同一个translation unit(TU)而不是不同的翻译单元中。 您在头文件中定义变量 initialized,该变量包含在不同的翻译单元中,然后每个 TU 都有一个名为 initialized 的符号,它打破了 one definition rule

我将如何定义'extern'变量并在同一个文件中初始化它(因为它稍后会在同一个文件中使用)

如果你想让变量在同一个文件中使用,为什么要设为extern?当您想在不同的 TU 之间共享同一个变量时,您需要使用 extern。 如果您需要在全局范围内仅在单个 TU 中使用它,您应该简单地将其放在 unnamed namespace 中。

【讨论】:

没有办法在同一个文件里做吗? @mkhan3189:对第二个问题的回答是否回答了您评论中的问题? 是的 :) 将其标记为答案,因为这确实回答了我的问题。我相信没有办法在同一个文件中初始化,因为它是外部的。 但在我将此标记为答案之前,您是否知道如何使用相同的变量在同一个文件中定义和声明(当然 extern 至少需要两个文件才能使用它和 static 为每个包含创建自己的变量副本)但是还有其他方法吗? (希望问题很清楚) @mkhan3189:这是不可能的,因为您不能在头文件中定义对象并将此头包含在多个文件中。它违反了 ODR。

以上是关于外部变量导致多重定义错误的主要内容,如果未能解决你的问题,请参考以下文章

使用带有结构/数组的头文件的指针问题,导致多重定义错误(C)

error 找到一个或多个多重定义的符号的解决方法

gcc:在 C++ 应用程序中链接 C 库会导致“多重定义”错误

“多重定义”,“此处首先定义”错误

在多文件中C语言中全局变量的重定义

在多文件中C语言中全局变量的重定义