C++でusing namespace stdを使うと、衝突せずにコンパイルが通ってしまう場合があることを知った。
http://stackoverflow.com/questions/1452721/why-is-using-namespace-std-considered-bad-practice#1453605
例えばこんなコード。
conflict.cpp
#include <algorithm>
#include <cstdio>
//このmin関数はあってもなくてもコンパイルは通るが実行結果は全く異なる
int min(int a,int b){return a+b;}
using namespace std;
int main(){
printf("%d\n",min(2,3));
return 0;
}
衝突する場合しか知らなかったのですが、これは怖いですね…。
で、同じようなことをJava/C#でやってみたらできてしまったのでコードを紹介。
conflict.java
import java.util.*;
//このRandomクラスはあってもなくてもコンパイルは通るが実行結果は全く異なる
class Random{
public int nextInt(){return 123456789;}
}
class Main{
public static void main(String[]args){
System.out.println((new Random()).nextInt());
}
}
- 異なるパッケージをワイルドカードでインポートしてクラスが衝突したら完全修飾名しか許容しない
- パッケージ名.クラス名でインポートすることは1度しかできず、そのクラスは必ずクラス名のみで使える
- 上の例のRandomクラスはこれに相当
conflict.cs
using System;
//このRandomクラスはあってもなくてもコンパイルは通るが実行結果は全く異なる
class Random{
public int Next(){return 123456789;}
}
class Conflict{
static void Main(){
Console.WriteLine((new Random()).Next());
}
}
- 異なる名前空間をインポートしてクラスが衝突したら完全修飾名しか許容しない
- usingディレクティブで(長い)名前空間に別名をつけることは可能
C++も今の状況になったら例えば::minかstd::minしか許容しなくなるようなオプション付けばよいですね。実行前に気づけるので。
…だったら必ずstd::使えばよいのか。using namespace stdして一部の例外だけstd::使うのは気持ち悪いということにもなるし。