Pertama, beberapa terminologi:
- menggunakan-deklarasi :
using std::vector;
- menggunakan-direktif :
using namespace std;
Saya pikir menggunakan direktif penggunaan baik-baik saja, selama mereka tidak digunakan pada lingkup global di file header. Jadi memiliki
using namespace std;
dalam file .cpp Anda sebenarnya tidak menjadi masalah, dan jika ternyata, itu sepenuhnya di bawah kendali Anda (dan bahkan dapat dicakup ke blok tertentu jika diinginkan). Saya tidak melihat alasan partiklar untuk mengacaukan kode dengan banyak std::
kualifikasi - itu hanya menjadi sekumpulan gangguan visual. Namun, jika Anda tidak menggunakan sejumlah besar nama dari std
namespace di kode Anda, saya juga melihat tidak ada masalah dengan meninggalkan arahan. Ini tautologi - jika arahan tidak diperlukan, maka tidak perlu menggunakannya.
Demikian pula, jika Anda bisa bertahan dengan beberapa menggunakan-deklarasi (daripada menggunakan-direktif ) untuk tipe spesifik di std
namespace, maka tidak ada alasan Anda tidak boleh hanya membawa nama-nama spesifik itu ke namespace saat ini. Dengan cara yang sama, saya pikir itu akan menjadi gila dan kerumitan pembukuan untuk memiliki 25 atau 30 deklarasi penggunaan ketika satu petunjuk penggunaan akan melakukan trik dengan baik.
Juga baik untuk diingat bahwa ada kalanya Anda harus menggunakan deklarasi menggunakan. Lihat "Item 25: Pertimbangkan dukungan untuk pertukaran non-lempar" Scott Meyers dari Effective C ++, Edisi Ketiga. Untuk memiliki fungsi generik dan templated menggunakan metode swap 'terbaik' untuk tipe berparameter, Anda perlu menggunakan pencarian yang bergantung pada deklarasi penggunaan dan argumen (alias pencarian ADL atau Koenig):
template< typename T >
void foo( T& x, T& y)
{
using std::swap; // makes std::swap available in this function
// do stuff...
swap( x, y); // will use a T-specific swap() if it exists,
// otherwise will use std::swap<T>()
// ...
}
Saya pikir kita harus melihat idiom umum untuk berbagai bahasa yang menggunakan ruang nama secara signifikan. Misalnya, Java dan C # menggunakan banyak ruang nama (bisa dibilang lebih dari C ++). Cara yang paling umum digunakan dalam namespace dalam bahasa tersebut adalah dengan membawanya ke ruang lingkup saat ini secara massal dengan ekuivalen menggunakan direktif. Hal ini tidak menyebabkan masalah yang tersebar luas, dan beberapa kali masalah tersebut ditangani dengan basis 'pengecualian' dengan menangani nama yang dimaksud melalui nama yang sepenuhnya memenuhi syarat atau dengan aliasing - seperti yang dapat dilakukan di C ++.
Herb Sutter dan Andrei Alexandrescu mengatakan ini di "Item 59: Jangan tulis penggunaan namespace di file header atau sebelum #include" pada buku mereka, C ++ Coding Standards: 101 Rules, Guidelines, dan Best Practices:
Singkatnya: Anda dapat dan harus menggunakan namespace menggunakan deklarasi dan arahan secara bebas dalam file implementasi Anda setelah #include
arahan dan merasa nyaman karenanya. Meskipun pernyataan berulang yang bertentangan, namespace yang menggunakan deklarasi dan arahan tidak jahat dan tidak mengalahkan tujuan namespace. Sebaliknya, itulah yang membuat namespace dapat digunakan.
Stroupstrup sering dikutip mengatakan, "Jangan mencemari namespace global", dalam "Bahasa Pemrograman C ++, Edisi Ketiga". Dia sebenarnya mengatakan itu (C.14 [15]), tetapi mengacu pada bab C.10.1 di mana dia mengatakan:
Sebuah menggunakan-deklarasi menambahkan nama untuk lingkup lokal. A using-directive tidak; itu hanya membuat nama dapat diakses dalam cakupan di mana mereka dideklarasikan. Sebagai contoh:
namespaceX {
int i , j , k ;
}
int k ;
void f1()
{
int i = 0 ;
using namespaceX ; // make names from X accessible
i++; // local i
j++; // X::j
k++; // error: X::k or global k ?
::k ++; // the global k
X::k ++; // X’s k
}
void f2()
{
int i = 0 ;
using X::i ; // error: i declared twice in f2()
using X::j ;
using X::k ; // hides global k
i++;
j++; // X::j
k++; // X::k
}
Nama yang dideklarasikan secara lokal (dideklarasikan dengan deklarasi biasa atau dengan deklarasi menggunakan) menyembunyikan deklarasi nonlokal dengan nama yang sama, dan setiap overloading ilegal dari nama tersebut terdeteksi pada titik deklarasi.
Perhatikan kesalahan ambiguitas untuk k++
dalam
f1()
. Nama global tidak lebih diutamakan daripada nama dari namespace yang dapat diakses dalam lingkup global. Hal ini memberikan perlindungan yang signifikan terhadap benturan nama yang tidak disengaja, dan - yang terpenting - memastikan bahwa tidak ada keuntungan yang bisa diperoleh dari pencemaran namespace global.
Saat library yang mendeklarasikan banyak nama dibuat dapat diakses melalui using-directives, ada keuntungan signifikan bahwa benturan nama yang tidak digunakan tidak dianggap sebagai error.
...
Saya berharap melihat penurunan drastis dalam penggunaan nama global dalam program baru yang menggunakan ruang nama dibandingkan dengan program C dan C ++ tradisional. Aturan untuk namespace secara khusus dibuat untuk tidak memberikan keuntungan bagi pengguna nama global yang '' malas '' dibandingkan seseorang yang berhati-hati untuk tidak mencemari cakupan global.
Dan bagaimana seseorang memiliki keuntungan yang sama sebagai 'pengguna malas nama global'? Dengan memanfaatkan arahan using, yang dengan aman membuat nama di namespace tersedia untuk cakupan saat ini.
Perhatikan bahwa ada perbedaan - nama dalam std
namespace yang tersedia untuk cakupan dengan penggunaan yang tepat dari direktif penggunaan (dengan menempatkan direktif setelah #includes
) tidak mencemari namespace global. Itu hanya membuat nama-nama itu tersedia dengan mudah, dan dengan perlindungan berkelanjutan terhadap bentrokan.