5

以前に定義された変数を使用するためにexternを使用しようとしています。

以前はexternを使用したことがありませんが、変数を1回だけ定義して複数のファイルで使用するには、externを使用する必要があります。

私はこの質問のために最小化されたバージョンのコードを書きました。私は4つのファイルを持っています

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'変数を定義し、同じファイルで初期化するにはどうすればよいですか(後で同じファイルで使用されるため)
4

1 に答える 1

8

lib.hガードの定義が存在するのになぜ複数回含まれるのか

定義を削除する必要があります:

bool initialized = false;

そして、それを唯一のソースファイルに入れます。

インクルードガードは、同じヘッダーファイルが異なる翻訳ユニットではなく同じ翻訳ユニット(TU)に複数回インクルードされるのを防ぎます。
異なる変換ユニットにインクルードされるヘッダーファイルで変数initializedを定義すると、各TUには、 1つの定義ルールinitializedに違反するという名前のシンボルがあります。

'extern'変数を定義し、同じファイルで初期化するにはどうすればよいですか(後で同じファイルで使用されるため)

変数を同じファイルで使用したい場合は、なぜそれを作成するのexternですか?extern異なるTU間で同じ変数を共有する場合に使用する必要があります。
単一のTUのみのグローバルスコープで使用する必要がある場合は、名前のない名前空間内に配置するだけです。

于 2013-01-26T06:38:18.600 に答える