12

A.cpp と B.cpp のような 2 つのファイルがあります。

A.cpp
----------
class w
{
public:
    w();
};


B.cpp
-----------
class w
{
public:
    w();
};

今、どこか ( https://en.cppreference.com/w/cpp/language/static ) で、クラスに外部リンケージがあることを読みました。そのため、ビルド中に複数の定義エラーが発生することを期待していましたが、逆に魅力的に機能しました。しかし、A.cpp でクラス w を定義すると、再定義エラーが発生し、クラスに内部リンケージがあると思われます。

ここで何か不足していますか?

4

6 に答える 6

7

技術的には、マキシムが指摘しているように、リンケージはシンボルに適用され、シンボルが示すエンティティには適用されません。ただし、シンボルのリンケージは、その意味によって部分的に決定されます。名前空間スコープで定義されたクラスに名前を付けるシンボルは外部リンケージを持ち、との両方でw同じエンティティを示します。A.cppB.cpp

C ++には、エンティティの定義に関する2つの異なるルールセットがあります。関数や変数などの一部のエンティティは、プログラム全体で1回だけ定義できます。それらを複数回定義すると、未定義の動作が発生します。ほとんどの実装では(とにかくほとんどの場合)複数定義エラーが発生しますが、これは必須ではなく、保証もされていません。クラスやテンプレートなどの他のエンティティは、それらを使用する各翻訳ユニットで定義する必要があります。さらに、すべての定義が同一である必要があります。トークンの同じシーケンス、および同じエンティティにバインドされるすべてのシンボルは、非常に限られています。定数式のシンボルの例外。ただし、アドレスが取得されることはありません。これらの要件に違反することも未定義の動作ですが、この場合、ほとんどのシステムは警告すらしません。

于 2011-06-24T09:12:58.273 に答える
0

外部リンケージは、プログラム全体でシンボル (関数またはグローバル変数) にアクセスできることを意味し、内部リンケージは、1 つの翻訳単位でのみアクセスできることを意味します。extern および static キーワードを使用してシンボルのリンケージを明示的に制御します。デフォルトのリンケージは、非 const シンボルの場合は extern であり、const シンボルの場合は static (internal) です。

外部リンケージを持つ名前は、同じスコープまたは同じ翻訳単位の他のスコープ (内部リンケージと同様)、またはさらに他の翻訳単位で宣言された名前を介して参照できるエンティティを示します。

プログラムは実際にはOne Definition Ruleに違反していますが、コンパイル単位が異なるため、コンパイラがエラーを検出するのは困難です。そして、リンカーでさえそれをエラーとして検出できないようです。

C++ では、名前空間を利用して One Definition Rule をバイパスする回避策が可能です。

[更新] C++03 標準
§ 3.2 1 つの定義規則から、セクション 5 は次のように述べています。

各定義が異なる翻訳単位に現れ、定義が次の要件を満たしている場合、プログラム内にクラス型 ... の複数の定義が存在する可能性があります。Dという名前のエンティティが複数の翻訳単位で定義されている場合、Dの各定義は同じ一連のトークンで構成されます。

于 2011-06-24T08:43:34.190 に答える
0

クラスには、ペダンティックになるためのリンケージはありません。

symbolsリンケージは、関数と変数、またはコードとデータにのみ適用されます。

于 2011-06-24T08:45:24.567 に答える