宣言

宣言の種類

宣言には次の種類があります。

  • 関数定義 (function-definition)
  • リンケージ指定 (linkage-specification)
  • テンプレート指定 (template-specification)
  • エイリアス テンプレート (alias templates)
  • 明示的なテンプレートのインスタンス化 (explicit-template-instantiation)
  • 明示的なテンプレートの指定 (explicit-template-specialization)
  • 名前空間定義 (namespace-definition)
  • 名前空間エイリアス定義 (namespace-alias-definition)
  • エイリアス宣言 (alias-declaration)
  • using宣言 (using-declaration)
  • usingディレクティブ (using-directive)
  • ASM定義 (asm-definition)
Declarations | MSDN

文法

指定子 基本型 宣言子 初期設定子
  • 指定子 (specifier)
  • 基本型 (base type)
  • 宣言子 (declarator)
    • * … ポインタ
    • & … リファレンス
    • [] … 配列
    • () … 関数
  • 初期設定子 (initializer)

宣言指定子 (declaration specifiers)

  • ストレージ クラス指定子 (storage-class-specifier)
  • 型指定子 (type-specifier)
    • void
    • char
    • short
    • int
  • 関数指定子 (function-specifier)
指定子 | MSDN 宣言子 | MSDN

複数の名前の宣言

宣言子は個々の名前にしか適用されません。よって、

int* a, b;

と記述するのは

int *a;
int b;

とするのと同じです。よってこれは

int *a, *b;

とすべきです。

型修飾子 (type qualifier)

定数 (const)

const declaration;
member-function const; // 定数メンバ関数
const (C++) | MSDN
const int a = 1;
a = 2; // error C3892: 'a': const である変数へは割り当てることはできません
a++;   // error C2105: '++' には左辺値が必要です。

int s1 = 10;
int p1[s1]; // error C2131: 式は定数に評価されませんでした

const int s2 = 10;
int p2[s2]; // ok

定数とポインタ

int p1[] = { 1, 2, 3 };
int* p2 = new int[3];

// 定数を指すポインタ
const int* cp = p1;
cp[0] = 10; // error C3892: 'cp': const である変数へは割り当てることはできません
cp = p2;    // ok

// ポインタ定数
int* const pc = p1;
pc[0] = 10; // ok
pc = p2;    // error C3892: 'pc': const である変数へは割り当てることはできません

// 定数を指すポインタ定数
const int* const cpc = p1;
cpc[0] = 10; // error C3892: 'cpc': const である変数へは割り当てることはできません
cpc = p2;    // error C3892: 'cpc': const である変数へは割り当てることはできません
区分 表記 ポインタのアドレスの変更 ポインタが指すアドレスにある内容の変更
定数を指すポインタ const type* ×
ポインタ定数 type* const ×
定数を指すポインタ定数 const type* const × ×

Volatile

ハードウェアによって値が変更される可能性があることをコンパイラに示します。これによりコンパイラによる最適化を抑制することができます。volatile (C++) | Microsoft Learn

同義語の宣言 (typedef)

型のシノニム (同義語) を宣言できます。

typedef type-declaration synonym;
typedef 指定子 | MSDN

この場合、すでに定義されている型type-declarationに対して、synonymが新しい名前となります。

typedef unsigned char uchar;

uchar a;
typedef char CHAR;
typedef CHAR *PSTR;

このように宣言された型でさらに新しい型を宣言する場合には、次のようにカンマ区切りで記述します。

typedef char CHAR, *PSTR;

typedefは通常の識別子と同様のスコープを持ちます。typedef 名の名前空間 | MSDN

ストレージ クラス (Storage classes)

ストレージ クラスは、以下を制御する型指定子です。

  • オブジェクトの有効期間
  • オブジェクトのリンケージ
  • オブジェクトのメモリの場所
宣言場所 指定子 他ファイルからの参照 適用範囲 生存期間
関数ブロック内 static × その関数ブロック内のみ 最初から最後まで
extern
関数ブロック外 static × コンパイル単位全体
extern

auto

  • Visual C++ 2010より前 … ローカルでの有効期限を持つ、自動ストレージ クラス
  • Visual C++ 2010移行 … 初期化子から推定して型を決定
auto キーワード | MSDN

static

staticなオブジェクトは、プログラムの起動時に割り当てられ、終了時に解放されます。

使用可能なスコープ
  ローカル グローバル 名前空間 クラス
変数
関数 ×
静的 - ストレージ クラス (C++) | MSDN

静的メンバ

extern

他ファイルから参照できるように、外部リンケージがあるものとして宣言できます。

extern string-literal { declaration-list }
extern string-literal declaration

Microsoft C++はstring-literalとして"C"と"C++"をサポートし、C++プログラムから利用できるように標準的なインクルード ファイルはextern "C"を使用します。

// Cリンケージを持つようにヘッダを読み込み
extern "C"
{
    #include <sample.h>
}


// Cリンケージを持つ関数の宣言
extern "C" void Func1();

// ... 複数の関数をまとめて宣言
extern "C"
{
    void Func1();
    void Func2();
}

// ... 関数の定義
extern "C" void Func1()
{
}


// Cリンケージを持つ変数の宣言
extern "C" int x;

__declspec

Microsoft固有の仕様で、ストレージクラスを拡張する属性を付加できます。

__declspec ( extended-decl-modifier-seq )
__declspec | Microsoft Learn
属性 作用
align 配置を制御する
allocate データ項目が割り当てられる、データ セグメントの名前を指定する
appdomain マネージド アプリケーションの各アプリケーション ドメインは、特定のグローバル変数または静的メンバー変数の独自のコピーを持つ必要があることを指定する
code_seg .objファイル内で関数やクラス メンバー関数のオブジェクト コードが格納される、実行可能なテキスト セグメントを指定する
deprecated いくつかの例外を除き、deprecated pragmaと同じ
dllexport 関数、データ、オブジェクトを、DLLとの間でエクスポートできる
dllimport 関数、データ、オブジェクトを、DLLとの間でインポートできる
jitintrinsic 64ビット共通言語ランタイムにとって重要な関数であることを示す
naked コンパイラにプロローグおよびエピローグ コードのないコードを生成するように指示する
noalias ポインタ パラメータによって示されるdirectlyが指すメモリ ポインタしか、変更しないことを意味する
noinline 特定のメンバー関数 (クラス内の関数) を、インラインにしないことをコンパイラに伝える
noreturn コンパイラに、関数が戻らないことを伝える
nothrow 関数とそれが呼び出す関数が、例外をスローしないことをコンパイラに伝える
novtable クラスのコンストラクターおよびデストラクター内のvfptrを初期化するコードをコンパイラが生成することを阻止する
process マネージド アプリケーション プロセスが、プロセス内のすべてのアプリケーション ドメイン間で共有される特定のグローバル変数、静的メンバー変数、静的ローカル変数の、コピーを1つ持つことを指定する
restrict 関数が他のポインターで別名を与えられないオブジェクトを返すことをコンパイラに伝える
safebuffers 関数のバッファー オーバーラン セキュリティ チェックを挿入しないようにコンパイラに伝える
selectany 宣言されたグローバル データ項目がpick-any COMDAT (パッケージ化された関数) であることをコンパイラに伝える
thread スレッド ローカル変数を宣言する
uuid コンパイラはクラスや構造体の宣言や定義に、GUIDを添付する

名前空間 (Namespaces) / ネームスペース

名前空間を用いた宣言

namespace MyNamespace
{
    void Func1();
    void Func2();
}

名前空間を用いた定義

void MyNamespace::Func1() {}
void MyNamespace::Func2() {}

using宣言 (using declaration)

void main()
{
    MyNamespace::Fun1();
}
void main()
{
    using MyNamespace::Fun1; // 関数名まで指定
    using MyNamespace::Fun2;

    Fun1(); // 名前空間は不要
    Fun2();
}

usingディレクティブ (using directive)

namespace MyNamespace1
{
    void Func1();
    void Func2();

    using namespace MyNamespace2;
}
using directives - Namespaces (C++) | Microsoft Learn

usingディレクティブをヘッダー ファイルに記述しないようにします。記述すると、それをインクルードするすべてのファイルに適用され、名前の隠蔽や競合を起こす恐れがあります。

名前空間エイリアス (namespace alias)

namespace MyNamespace { class MyClass {}; }

namespace A = MyNamespace;

void Func(A::MyClass myClass){ }
名前空間エイリアス - 名前空間 (C++) | MSDN

グローバル名前空間 (global namespace)

グローバル スコープで宣言されている関数には、次のようにしてもアクセスできます。

::Func();

参考

参考書

参考

参考書

Microsoft Learnから検索