最近C++のインタビューを受けましたが、コンパイラは2つの異なるクラスで同じ名前の静的データメンバーをどのように区別しますか?
すべての静的データ変数はデータセグメントに格納されるため、特に同じ名前の場合、コンパイラがどの静的データがどのクラスに属しているかを追跡する方法が必要です。
編集:私は名前マングリングに答えましたが、彼は名前マングリングが同じクラスのメンバーの間でのみ使用されていると言って拒否しました。
最近C++のインタビューを受けましたが、コンパイラは2つの異なるクラスで同じ名前の静的データメンバーをどのように区別しますか?
すべての静的データ変数はデータセグメントに格納されるため、特に同じ名前の場合、コンパイラがどの静的データがどのクラスに属しているかを追跡する方法が必要です。
編集:私は名前マングリングに答えましたが、彼は名前マングリングが同じクラスのメンバーの間でのみ使用されていると言って拒否しました。
名前は、クラス名が含まれている状態でマングルされています。clangコンパイラの例
class A {
static int i;
};
int A::i = 0;
出力
$ clang++ -cc1 -emit-llvm main1.cpp -o -
; ModuleID = 'main1.cpp'
target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:32:32-n8:16:32"
target triple = "i386-pc-linux-gnu"
@_ZN1A1iE = global i32 0, align 4
どこ_ZN1A1iE
にありますか
$ c++filt _ZN1A1iE
A::i
これは実装定義であるため、実行する必要のある方法は1つではありません。
ただし、名前マングリングは一般的に使用されます。
名前マングリングによって、クラスの名前もデータでエンコードされていると思います。名前の前に付けるのと同じくらい簡単な場合でも、私は驚かないでしょう。
class one
{
static int data;
};
class two
{
static int data;
};
名前を持つことができます
one::data
two::data
データセグメント内。それらは一意の名前です。
名前は、人間が物事に意味を与えるために使用するものです。
コンパイラがそれらが異なるアイテムであることを認識すると(異なるクラスで宣言されているため)、バイナリ内でそれらを区別するために名前を使用せず、ポインタを使用し、ポインタは名前を気にしません:)
その場合、データの名前の前にクラスを含めることを禁じるものはありません。
すべての「名前マングリング」の回答は、デバッガーが各シンボルのストレージを見つける方法と、リンカーが違いを認識する方法に対応していますが、これらのエンティティはシンボルテーブルの異なるエントリを占めるため、コンパイラーは認識します。
それでおしまい。
実行可能ファイルは、名前について何も知る必要はありません{*}。ただの場所。コンパイラーは名前を知っており、その知識はシンボルテーブルにコード化されています(ただし、実装されている場合もあります)。
{*}とにかく、RTTIがない場合。
クラスの名前は、メンバーの名前を修飾しますmyclass::mymemb
。コンパイラは、クラスの外部からそれらを参照する場合と同じようにそれらを区別します。
実装内では、これは名前マングリングによって行われます。コンパイラーは、クラスの名前とメンバーの名前をサンティエートし、それらを一緒に連結して、などの混乱を引き起こします__i_7myclass_6mymemb
。
extern "C"
名前マングリングプロセス(またはその必要性)が、マングルされていない名前を定義するCインターフェイスとの互換性が必要な理由です。
static
クラスのメンバーは、クラス名がリンカから見た「グローバル」名の一部になるように名前が変更されます。
クラス名をデータメンバー名に付加します。(そして、名前がすべてを壊します。)