名前修飾
C++のシンボルはDLLや共有オブジェクトを通してルーチン的にエクスポートされるため、名前修飾スキームはコンパイラの問題だけではすまなくなる。ライブラリをコンパイルするにあたって、複数のコンパイラ(場合によっては、同じコンパイラでも版が異なるだけで問題になりうる)によって名前修飾がそれぞれ異なったスキームで行われると、それらのライブラリを参照する際、しばしばシンボルが解決できなくなってしまう。例えば、複数のC++コンパイラ(例えば、GCCとOS付属のコンパイラ)が導入されているシステムにBoost C++ライブラリを導入しようとすると、二度それをコンパイルしなければならない(GCCで1回、OS付属のコンパイラで1回)。
このため、名前修飾はC++が関係したABIでの重要な側面の一つとなっている。
名前修飾を行う処理系のうち、C++コンパイラは最も広く用いられているが、最も標準化が進んでいないものである。最初のC++コンパイラはCソースコードへのトランスレータとして実装された。そのため、シンボルの名前はCの識別子の規則に従う必要があった。後にC++コンパイラ自身が機械語コードやアセンブラコードを出力するようになっても、計算機システムのリンカは総じてC++のシンボルをサポートせず、名前修飾が必要な状態が続いた。
C++言語は、標準的な修飾規則を定めていない。そのため、コンパイラによって修飾規則が異なる。(クラス、テンプレート、演算子オーバーロードなどの情報を格納する)C++の修飾がかなり複雑になりうることも加わり、異なるコンパイラのオブジェクトコードはリンクすることができないのが通常である。
内部クラス (inner class) のスコープは、その親クラスに制限される。そのため、コンパイラは「修飾付きの」 (qualified) パブリックな名前を内部クラスに対して与えなければならない。同様に無名(匿名)クラス (anonymous class) には「偽の」パブリックな名前を生成しなければならない(無名クラスはコンパイラの概念であり、実行時には関係がない)。そこで、次のJavaプログラムをコンパイルすると
3つの .class ファイルが生成される。
Foo.class: 主クラス(外側のクラス)Foo を含む。
Foo$bar.class: Foo.bar という名前付きの内部クラスを含む。
Foo$1.class: メソッド Foo.zark に対して局所的な無名の内部クラスを含む。
ドル記号 ($) はJava仮想マシン (JVM) の仕様上許されているので、これら3つのクラス名は全て有効であり、Java言語の仕様上 $ は通常のJavaクラス定義に用いることができないので、コンパイラは安全にこれらの名前を利用することができる。
完全修飾名は特定のクラスローダインスタンスの内部でのみ一意であるので、実行時にはJavaにおける名前の解決は更に複雑である。クラスローダは階層性をもっており、JVMの各スレッドはいわゆる文脈クラスローダ (context class loader) を持っている。そこで、2つの異なったクラスローダインスタンスが同じ名前のクラスを含むとき、システムは初めルート(あるいはシステム)クラスローダを用いてクラスをロードしようとし、次いで階層に従って文脈クラスローダをたどる。