1

ヘッダーで既に静的固定長配列を再定義しているにもかかわらず、コンパイラーがコンパイル単位で静的固定長配列を再定義する必要がある理由を説明していただければ幸いです。次に例を示します。

MyClass.h:

#ifndef MYCLASS_H
#define MYCLASS_H

class MyClass {
private:
    static char myPrecomputeTable[256];
}

#endif

MyClass.cpp

#include "MyClass.h"

char MyClass::myPrecomputeTable[256];

MyClass.cpp の再定義を削除すると、リンカは myPrecomputeTable が未定義であると不平を言います。構文は冗長なようです。コンパイラ/リンカーが定義を必要とする理由を誰かに説明してもらえますか?

編集:

申し訳ありませんが、私が混乱していたことについて明確ではなかったと思います。宣言/定義の概念を理解しています。興味深いのは、配列のサイズを定義することです。定義と宣言の両方で、冗長に見えるサイズを定義する必要があります。

編集:

もう少し掘り下げてみたところ、このトピックへの多くのアプローチがコンパイラに適していることがわかりました。コンパイル:

MyClass.h
class MyClass {
    static char myPrecomputeTable[256];
};

MyClass.cpp
char MyClass::myPrecomputeTable[256];

コンパイル:

MyClass.h
class MyClass {
    static char myPrecomputeTable[];
};

MyClass.cpp
char MyClass::myPrecomputeTable[256];

コンパイル:

MyClass.h
class MyClass {
    static char myPrecomputeTable[256];
};

MyClass.cpp
char MyClass::myPrecomputeTable[];

コンパイルしない:

MyClass.h
class MyClass {
    static char myPrecomputeTable[512];
};

MyClass.cpp
char MyClass::myPrecomputeTable[256];

サイズは、ヘッダーまたはクラス、あるいはその両方で定義する必要がありますが、コンパイラは競合するサイズを停止するのに十分スマートです。

4

2 に答える 2

6

ヘッダー内:

class MyClass {
private:
    static char myPrecomputeTable[256];
}

宣言です。

そして .cpp で:

char MyClass::myPrecomputeTable[256];

定義です。

宣言は、シンボルの基本的な属性(タイプと名前) を提供します。

定義は、そのシンボルのすべての詳細を提供します。それが関数の場合は、それが何をするか。クラスの場合、どのフィールドとメソッドがあるか。変数の場合、その変数が格納されている場所。

多くの場合、コンパイラは、リンカーが別のファイルから定義を見つけることができることを期待して、ファイルをオブジェクト ファイルにコンパイルするために何かの宣言のみを必要とします。ソース ファイルでシンボルが定義されていないにもかかわらず宣言されている場合、リンク時に未定義のシンボルに関するエラーが発生します。

両方の違いを理解するための良いリンク: http://www.cprogramming.com/declare_vs_define.html


標準から:

3.1 宣言と定義 [basic.def]

  1. 宣言は、1 つまたは複数の名前を翻訳単位に導入したり、以前の宣言によって導入された名前を再宣言したりできます。その場合、宣言はこれらの名前の解釈と属性を指定します。宣言には、次のような効果もあります。

    • 静的アサーション (条項 7)、
    • テンプレートのインスタンス化の制御 (14.7.2)、
    • 属性の使用 (第 7 条)、および
    • なし (空宣言の場合)。
  2. 宣言は、関数の本体を指定せずに関数を宣言しない限り、定義externです。指定子またはリンケージ仕様を含み、初期化子関数本体も含まず、クラス定義で静的データ メンバーを宣言します。それはクラスです。 name 宣言opaque-enum-declaration、またはtypedef 宣言using-declaration、 static_assert-declaration 、attribute-declarationempty-declaration、またはusing-directiveです。

于 2013-08-01T14:25:17.157 に答える
2

ヘッダー ファイルの最初のものは単なる宣言であり、ヘッダー ファイルを含む他のすべてのソース ファイルに対してこのメ​​ンバーが存在することをコンパイラに伝えます。

ソース ファイルの 2 番目は実際の定義であり、プロジェクト全体を 1 つの実行可能ファイルにリンクするときにリンカーによって必要とされます。


コンパイラにサイズを 2 回伝えなければならない場合は、言語が動作するように指定されているだけです。あなた(または誰でも)がそれについてできることはあまりありません。

ただし、次の方法typedefで回避できます。

class MyClass
{
    typedef char PrecomputeTable_t[256];

    static PrecomputeTable_t myPrecomputeTable;
};

...

MyClass::PrecomputeTable_t MyClass::myPrecomputeTable;
于 2013-08-01T14:23:53.683 に答える