状況を明確にするために、これが C++ で変化することは想像できません。それを支持できる変更にすることを望んでも、C との互換性がなくなるまで型の安全性を強化する必要があります (たとえば、すべての暗黙的な変換をほぼ排除する必要があります)。
状況はかなり単純です。現在、名前の検索は、使用されている名前のインスタンスが少なくとも 1 つ含まれている最初のスコープで停止します。その名前のインスタンスが、名前を使用しようとした方法と一致しない場合、コンパイルは失敗します。
その時点で検索を停止する代わりに、コンパイラはスコープの検索を続行し、本質的にそれらすべての名前のオーバーロード セットを作成してから、最も一致するものを選択します。
このような場合、外部スコープでの一見些細な変更が、まったく意図せずにコードの意味を (完全に) 変更する可能性があります。たとえば、次のように考えてください。
int i;
int main() {
long i;
i = 1;
std::cout << i;
return 0;
}
現在の規則では、これの意味は明確で明確です。 は、定義されたローカルの toi=1;
に値 1 を代入します。i
main
改訂された規則の下では、それは疑問の余地があります-実際、おそらくそうであるべきではありません. コンパイラは と の両方のインスタンスを検出しi
、1
タイプが であるため、代わりint
にグローバルと一致する可能性があります。i
を出力するi
と、コンパイラは を受け取るオーバーロードを検出するlong
ため、ローカルi
(まだガベージが含まれています) を出力します。
ただし、これにより別の問題が追加されることに注意してください。ローカルで動作する可能性のあるオーバーロードがあったためcout << i;
、ローカルを参照することになります。したがって、使用されたオーバーロードを制御する変数の型の代わりに、使用された変数も制御する利用可能なオーバーロードを持つことになります。よくわかりませんが、これにより解析がはるかに困難になると思います(おそらく、NP困難またはNP完全な問題です)。i
要するに、(意図的またはその他の方法で) ほぼすべての種類の暗黙的な変換を内部スコープで使用するコードは、外部スコープでのこの一見無関係な変更により、そのコードの意味が突然完全に変更される可能性があり、上記の例のように、簡単に壊れることがあります。その過程でかなり徹底的に。
上記の例では、わずか 6 行のコードで、何が起こっているのかを簡単に把握できます。ただし、(たとえば) ヘッダーでクラスを定義し、そのヘッダーを他のファイルにインクルードするとどうなるかを考えてみてください。コンパイラは、ヘッダーをインクルードした他のコードを調べ、より適切なコードを見つけ、突然コーディングします。あなたは、徹底的に吟味され、最も見事な休憩をテストしたと誓った.
ただし、ヘッダーを使用すると、さらに悪化する可能性があります (または、少なくとも可能性があります)。クラスを定義し、ヘッダーを 2 つの異なるファイルに含めます。これらのファイルの 1 つは外部スコープで変数、関数などを定義し、もう 1 つは定義しません。Xという名前を使用する1つのファイルのコードはグローバルを参照し、他のファイルのコードはローカルを参照します。これは、グローバルがそのファイルに表示されないためです。これにより、モジュール性が完全に失われ、事実上すべてのコードが完全に壊れてしまいます (少なくとも壊れる可能性があります)。
もちろん、これほど壊れていない可能性は他にもあります。1 つの可能性は、すべての暗黙的な変換を排除することです。そのため、完全な型の一致のみが考慮されます。これにより、明らかな問題のほとんどが解消されますが、 C との互換性が完全に失われるという代償が伴います (言うまでもなく、おそらく多くのプログラマーが不満を抱くでしょう)。もう 1 つの可能性は、現在のように検索し、一致が見つかった最初のスコープで停止することです。次に、内側のスコープでその名前を使用した場合にコンパイルが失敗する場合にのみ、外側のスコープに進みます。
どちらでも機能しますが、(少なくとも) 非常識なレベルの混乱を招かないようにするには、かなりの制限が必要です。たとえば、a =1; a = '\2';
今のところ、これらは同じ変数を参照する必要がありますが、最初のルールではそうではありません。
いくつかの特殊なケースでは、おそらくその特定の奇妙さを排除することもできます。たとえば、変数名の検索には現在のルールを使用し、関数名のみに新しい/別のルールを使用します。
要約: これを行うための単純で明白な方法は、ほとんど取り返しのつかないほど壊れた言語を作成します。それを防ぐための変更は可能ですが、C と本質的にすべての既存の C++ コードの両方との互換性を捨てることを犠牲にしてのみです。後者は、まったく新しい言語で可能かもしれませんが、C++ のようにすでに確立されている言語 (特に、後方互換性に基づいて確立された言語、つまり C++) では可能です。