C++ の Pragma Once
この記事は、プリプロセッサディレクティブとしての pragma once
の概要と、その使用方法の簡単な例から始まります。この後、C および C++ でのサポートに関する pragma once
のいくつかの特定のプロパティについて説明し、最後に、その使用方法と代替手段よりも優れている方法のより包括的な例を示します。
C++ の Pragma Once
pragma once
は、C および C++ でプリプロセッサディレクティブとして使用されます。プリプロセッサディレクティブは、プログラムを構成せず、代わりにプリプロセッサによって読み取られる 1 行のコードです。
プリプロセッサは、コードをコンパイルする前にこれらを分析します。プリプロセッサは、これらのディレクティブの最後にセミコロンを期待していません。
したがって、pragma once
ディレクティブをコードに追加するには、ファイルの先頭に以下を追加します。
#pragma once
pragma once
自体は非標準です。これは、一部のコンパイラがそれをサポートしないことを意味し、その複雑な実装のために、常に信頼できるとは限りません。
ただし、これは非常に一般的にサポートされています。したがって、ほとんどの場合、プラグマを 1 回
使用しても問題はありません。その目的は単純です。現在のソースファイル(ディレクティブが書き込まれているファイル)がコンパイルに 1 回だけ含まれるようにします。
この作業は、include
guardsを使用して代わりに実行できます。pragma once
の使用方法の例の後で、違いについて説明します。
pragma once
は、主にクラスを定義するときに使用されます。次の例では、Structure
と Room
の 2つのクラスを定義します。
Room
クラスは Structure
クラスから継承されます。
// This contains the code for the Structure class
// Save this as Structure.h
#pragma once
#include <iostream>
#include <string>
using namespace std;
class Structure {
string struc_name;
int id;
public:
void setVals() {
struc_name = "Example Name";
id = 1;
}
void printVals() {
cout << "Name is: " << struc_name << " and id is: " << id << endl;
}
};
次に、Room
クラスを定義します。
// Save this as Room.h
#pragma once
#include "Structure.h"
class Room {
Structure example;
public:
void initRoom() { example.setVals(); }
void getRoom() { example.printVals(); }
};
これで、上記のオブジェクトを使用する main
関数を定義できます。
// save this in a main.cpp file
#include <iostream>
#include "Room.h"
#include "Structure.h"
using namespace std;
int main() {
Room testRoom;
testRoom.initRoom();
testRoom.getRoom();
return 0;
}
上記の例では、コードを実行すると、出力として Name is: Example Name and id is: 1
が出力されます。これは期待どおりです。ただし、プラグマを 1 回
削除すると、次のエラーが発生します。
In file included from Room.h:3,
from main.cpp:2:
Structure.h:8:7: error: redefinition of 'class Structure'
8 | class Structure
| ^~~~~~~~~
In file included from main.cpp:1:
Structure.h:8:7: note: previous definition of 'class Structure'
8 | class Structure
| ^~~~~~~~~
クラス Structure
は 2 回定義されています。pragma once
を使用すると、1 回だけ読み取られるようにすることができます。
別の方法は、代わりに識別子を使用することです。上記の例のコンテキストでは、以下に定義されているようにそれを行うことができます。
#ifndef STRUCTURE
#define STRUCTURE
class Structure {
// Some sample code here
};
#endif
上記の例では、STRUCTURE
は何にでも置き換えることができます。ただし、通常、クラスの名前に対応する名前を保持します。
ただし、ここで問題が発生する可能性があります。第一に、それはより冗長であり、手動の意思決定を必要とし、コンパイラーは、プロジェクト内のどこかでマクロ名を誤って使用するプログラマーからの保護がありません。
コンパイラは通常、コンパイル速度を上げるために pragma once
用に最適化されています。
Husnain is a professional Software Engineer and a researcher who loves to learn, build, write, and teach. Having worked various jobs in the IT industry, he especially enjoys finding ways to express complex ideas in simple ways through his content. In his free time, Husnain unwinds by thinking about tech fiction to solve problems around him.
LinkedIn