Saya berasal dari latar belakang Java, di mana paket digunakan, bukan ruang nama. Saya terbiasa menempatkan kelas yang bekerja bersama untuk membentuk objek lengkap ke dalam paket, dan kemudian menggunakannya kembali nanti dari paket itu. Tapi sekarang saya bekerja di C ++.
Bagaimana Anda menggunakan ruang nama di C ++? Apakah Anda membuat ruang nama tunggal untuk seluruh aplikasi, atau apakah Anda membuat ruang nama untuk komponen utama? Jika demikian, bagaimana Anda membuat objek dari kelas di ruang nama lain?
sumber
std
namespace menjadi simbol daripada menggunakanusing
sama sekali. Jadi saya selalu menulisstd::cout
ataustd::string
sekarang karena saya menyebutnya sekarang. Saya tidak akan pernah menulis begitu sajacout
.std
, saya pribadi menemukan ini jauh kurang penting ketika Anda berurusan dengan perpustakaan yang lebih kecil. Seringkali Anda hanya dapat menggunakanusing namespace FooBario;
, terutama jika Anda menggunakan banyak jenis dari perpustakaan.using namespace X;
harus dihindari dalam file header jika memungkinkan.mylibrary::endl
untuk mewakili urutan baris baru khusus saya sendiri. Maksud saya, mengapa menemukan nama?Untuk menghindari mengatakan semuanya, Mark Ingram telah mengatakan sedikit tip untuk menggunakan ruang nama:
Hindari direktif "using namespace" dalam file header - ini membuka namespace untuk semua bagian program yang mengimpor file header ini. Dalam file implementasi (* .cpp) ini biasanya bukan masalah besar - meskipun saya lebih suka menggunakan direktif "using namespace" pada tingkat fungsi.
Saya pikir namespaces sebagian besar digunakan untuk menghindari konflik penamaan - tidak harus mengatur struktur kode Anda. Saya akan mengatur program C ++ terutama dengan file header / struktur file.
Terkadang ruang nama digunakan dalam proyek C ++ yang lebih besar untuk menyembunyikan detail implementasi.
Catatan tambahan untuk arahan penggunaan: Beberapa orang lebih suka menggunakan "menggunakan" hanya untuk elemen tunggal:
sumber
using std::cout;
adalah deklarasi menggunakanusing std::cout, std::endl;
atau bahkanusing std::cout, endl;
,.using namespace x
dalam header jika itu dalam namespace lain. Itu bukan sesuatu yang saya sarankan secara umum tetapi tidak mencemari namespace global.Vincent Robert benar dalam komentarnya. Bagaimana Anda menggunakan ruang nama dengan benar di C ++? .
Menggunakan namespace
Namespaces paling tidak digunakan untuk membantu menghindari tabrakan nama. Di Jawa, ini diberlakukan melalui idiom "org.domain" (karena seharusnya seseorang tidak akan menggunakan apa pun selain dari nama domainnya sendiri).
Di C ++, Anda bisa memberikan namespace ke semua kode di modul Anda. Misalnya, untuk modul MyModule.dll, Anda bisa memberikan kode-nya namespace MyModule. Saya pernah melihat orang lain menggunakan MyCompany :: MyProject :: MyModule. Saya kira ini berlebihan, tetapi secara keseluruhan, tampaknya benar bagi saya.
Menggunakan "menggunakan"
Penggunaan harus digunakan dengan sangat hati-hati karena secara efektif mengimpor satu (atau semua) simbol dari namespace ke namespace Anda saat ini.
Ini jahat untuk melakukannya dalam file header karena header Anda akan mencemari setiap sumber termasuk (mengingatkan saya pada makro ...), dan bahkan dalam file sumber, gaya buruk di luar lingkup fungsi karena akan mengimpor pada lingkup global simbol dari namespace.
Cara paling aman untuk menggunakan "menggunakan" adalah dengan mengimpor simbol pilih:
Anda akan melihat banyak "using namespace std;" dalam tutorial atau contoh kode. Alasannya adalah untuk mengurangi jumlah simbol untuk membuat bacaan lebih mudah, bukan karena itu adalah ide yang bagus.
"menggunakan namespace std;" tidak disarankan oleh Scott Meyers (saya tidak ingat persis buku mana, tapi saya bisa menemukannya jika perlu).
Komposisi Namespace
Ruang nama lebih dari sekedar paket. Contoh lain dapat ditemukan dalam "Bahasa Pemrograman C ++ Bjarne Stroustrup".
Dalam "Edisi Khusus", di 8.2.8 Komposisi Namespace , ia menjelaskan bagaimana Anda dapat menggabungkan dua ruang nama AAA dan BBB menjadi yang lain yang disebut CCC. Dengan demikian CCC menjadi alias untuk AAA dan BBB:
Anda bahkan dapat mengimpor simbol pilihan dari ruang nama yang berbeda, untuk membangun antarmuka namespace kustom Anda sendiri. Saya belum menemukan penggunaan praktis ini, tetapi secara teori, itu keren.
sumber
Saya tidak melihat menyebutkannya di jawaban lain, jadi inilah 2 sen Kanada saya:
Pada topik "using namespace", pernyataan yang berguna adalah alias namespace, yang memungkinkan Anda untuk "mengganti nama" namespace, biasanya untuk memberikan nama yang lebih pendek. Misalnya, alih-alih:
kamu bisa menulis:
sumber
Jangan dengarkan setiap orang yang memberi tahu Anda bahwa ruang nama hanyalah ruang nama.
Mereka penting karena mereka dianggap oleh kompiler untuk menerapkan prinsip antarmuka. Pada dasarnya, ini dapat dijelaskan dengan sebuah contoh:
Jika Anda ingin mencetak objek A, kodenya adalah yang ini:
Perhatikan bahwa kami tidak secara eksplisit menyebutkan namespace saat memanggil fungsi. Ini adalah prinsip antarmuka: C ++ menganggap fungsi mengambil tipe sebagai argumen sebagai bagian dari antarmuka untuk tipe itu, jadi tidak perlu menentukan namespace karena parameter sudah menyiratkan namespace.
Sekarang mengapa prinsip ini penting? Bayangkan bahwa penulis kelas A tidak menyediakan fungsi print () untuk kelas ini. Anda harus menyediakannya sendiri. Karena Anda adalah programmer yang baik, Anda akan mendefinisikan fungsi ini di namespace Anda sendiri, atau mungkin di namespace global.
Dan kode Anda dapat mulai memanggil fungsi cetak (a) di mana pun Anda inginkan. Sekarang bayangkan bahwa bertahun-tahun kemudian, penulis memutuskan untuk menyediakan fungsi print (), lebih baik daripada Anda karena dia tahu internal kelasnya dan dapat membuat versi yang lebih baik dari Anda.
Kemudian penulis C ++ memutuskan bahwa versinya dari fungsi print () harus digunakan alih-alih yang disediakan di namespace lain, untuk menghormati prinsip antarmuka. Dan bahwa "peningkatan" fungsi print () ini semudah mungkin, yang berarti Anda tidak perlu mengubah setiap panggilan ke fungsi print (). Itu sebabnya "fungsi antarmuka" (fungsi dalam namespace yang sama dengan kelas) dapat dipanggil tanpa menentukan namespace di C ++.
Dan itulah mengapa Anda harus mempertimbangkan namespace C ++ sebagai "antarmuka" ketika Anda menggunakannya dan mengingat prinsip antarmuka.
Jika Anda ingin penjelasan yang lebih baik tentang perilaku ini, Anda dapat merujuk ke buku Exceptional C ++ dari Herb Sutter
sumber
Sebenarnya boost menggunakan banyak namespace, biasanya setiap bagian boost memiliki namespace sendiri untuk pekerjaan dalam dan kemudian hanya menempatkan antarmuka publik di boost namespace tingkat atas.
Secara pribadi saya berpikir bahwa semakin besar basis kode menjadi, ruang nama yang lebih penting menjadi, bahkan dalam satu aplikasi (atau perpustakaan). Di tempat kerja kami menempatkan setiap modul aplikasi kami di ruang namanya sendiri.
Penggunaan lain (tanpa maksud kata) dari namespaces yang saya gunakan banyak adalah namespace anonim:
Ini pada dasarnya sama dengan:
Namun, menggunakan namespace anonim (bukan statis) adalah cara yang disarankan agar kode dan data terlihat hanya dalam unit kompilasi saat ini di C ++.
sumber
const int CONSTANT = 42;
karena const tingkat atas dalam lingkup namespace sudah menyiratkan hubungan internal. Jadi Anda tidak perlu namespace anonim dalam kasus ini.Perhatikan juga bahwa Anda dapat menambahkan ke namespace. Ini lebih jelas dengan contoh, yang saya maksud adalah bahwa Anda dapat memiliki:
dalam file
square.h
, dandalam sebuah file
cube.h
. Ini mendefinisikan ruang nama tunggalMyNamespace
(yaitu, Anda dapat menentukan ruang nama tunggal di beberapa file).sumber
Di Jawa:
Dalam C ++:
Dan menggunakannya, Java:
Dan C ++:
Juga, nama lengkapnya adalah "somepackge.SomeClass" untuk Java dan "somenamespace :: SomeClass" untuk C ++. Menggunakan konvensi tersebut, Anda dapat mengatur seperti dulu di Jawa, termasuk membuat nama folder yang cocok untuk ruang nama. Folder-> paket dan file-> persyaratan kelas tidak ada, jadi Anda dapat memberi nama folder dan kelas secara mandiri dari paket dan ruang nama.
sumber
@ marius
Ya, Anda dapat menggunakan beberapa ruang nama sekaligus, misalnya:
[Feb. 2014 - (Apakah sudah begitu lama?): Contoh khusus ini sekarang ambigu, seperti yang ditunjukkan Joey di bawah ini. Boost dan std :: sekarang masing-masing memiliki shared_ptr.]
sumber
std
juga sudahshared_ptr
, jadi menggunakan keduanyaboost
danstd
ruang nama akan berbenturan ketika Anda mencoba menggunakan ashared_ptr
.Anda juga dapat memuat "using namespace ..." di dalam fungsi, misalnya:
sumber
Secara umum, saya membuat namespace untuk badan kode jika saya percaya mungkin ada konflik fungsi atau ketik nama dengan perpustakaan lain. Ini juga membantu untuk kode merek, ala boost :: .
sumber
Saya lebih suka menggunakan namespace tingkat atas untuk aplikasi dan sub ruang nama untuk komponen.
Cara Anda dapat menggunakan kelas dari ruang nama lain sangat mirip dengan cara di java. Anda dapat menggunakan "use NAMESPACE" yang mirip dengan pernyataan "import PACKAGE", mis. Use std. Atau Anda menentukan paket sebagai awalan dari kelas yang dipisahkan dengan "::", misalnya std :: string. Ini mirip dengan "java.lang.String" di Jawa.
sumber
Perhatikan bahwa namespace di C ++ benar-benar hanya ruang nama. Mereka tidak menyediakan enkapsulasi yang dilakukan oleh paket di Java, jadi Anda mungkin tidak akan menggunakannya terlalu banyak.
sumber
Saya telah menggunakan ruang nama C ++ dengan cara yang sama saya lakukan di C #, Perl, dll. Ini hanya pemisahan semantik simbol antara hal-hal perpustakaan standar, hal-hal pihak ketiga, dan kode saya sendiri. Saya akan menempatkan aplikasi saya sendiri di satu namespace, kemudian komponen pustaka yang dapat digunakan kembali di namespace lain untuk pemisahan.
sumber
Perbedaan lain antara java dan C ++, adalah bahwa dalam C ++, hirarki namespace tidak perlu mengatur tata letak sistem file. Jadi saya cenderung menempatkan seluruh pustaka yang dapat digunakan kembali dalam satu namespace, dan subsistem dalam pustaka dalam subdirektori:
Saya hanya akan meletakkan subsistem dalam ruang nama bersarang jika ada kemungkinan konflik nama.
sumber