Semakin besar sebuah program, semakin banyak nama yang beredar: variabel, konstanta, fungsi, dan tipe. Masalah muncul ketika dua bagian kode — atau dua pustaka berbeda — memilih nama yang sama; compiler tidak punya cara membedakan keduanya. Namespace (ruang nama) adalah fitur C++ yang memberi setiap kelompok nama “alamat rumah” sendiri sehingga nama yang identik bisa hidup berdampingan tanpa tabrakan. Pada Chapter ini kita melihat mengapa namespace diperlukan, membedah std:: yang selama ini kita tulis di depan cout, serta membahas kapan deklarasi using wajar dipakai dan kapan sebaiknya dihindari.
Masalah yang Diselesaikan Namespace #
Bayangkan kita memasang dua pustaka grafis, dan keduanya menyediakan fungsi bernama render. Tanpa namespace, dua deklarasi yang sama bertabrakan dan kompilasi gagal sebelum program sempat jalan. Dengan namespace, masing-masing pustaka menaruh render di dalam “kotak” miliknya sehingga keduanya bisa dipakai dalam satu program:
// Ilustrasi struktur (belum kita jalankan): nama sama, kotak berbeda
namespace pustaka_a {
void render();
}
namespace pustaka_b {
void render();
}Namespace adalah konstruksi murni bahasa — ia bukan folder file di disk, melainkan aturan penamaan yang dikenal compiler. Mendeklarasikannya mudah: kata namespace, pilih nama, lalu buka blok { } yang berisi nama-nama anggotanya. Anggota namespace biasanya berupa konstanta, fungsi, dan tipe; isi yang kita taruh di situ hanya bisa diakses lewat nama kotaknya. Pola ini juga dipakai oleh pustaka standar itu sendiri: hampir seluruh isinya tinggal di satu namespace besar bernama std.
Namespace std dan Operator Scope Resolution #
Setiap kali kita menulis std::cout, kita sebenarnya memakai operator :: (scope resolution operator) untuk menyatakan: “ambil cout yang anggota dari namespace std”. Dibaca dari kiri ke kanan, std::cout berarti nama cout milik std — bukan cout milik kita atau milik pustaka lain. Inilah alasan program kita tidak bertabrakan dengan pustaka standar walau kita menamai variabel count sendiri: versi kita hidup di namespace global, sedangkan milik pustaka ada di std.
Kualifikasi lengkap seperti std::cout memang lebih panjang, tetapi ia menyimpan informasi penting: asal-usul nama itu jelas terbaca di tempat pemakaiannya. Pada kode profesional, kualifikasi eksplisit adalah gaya yang paling banyak dipakai justru karena keterbacaan ini. Untuk program belajar yang pendek, menulis std:: berulang kali tetap cara paling aman — kebiasaan baik yang sebaiknya dibentuk sejak sekarang.
Mengangkat Nama dengan Deklarasi using #
Bila satu nama memang dipakai sangat sering, C++ menyediakan deklarasi using untuk “mengangkat” satu nama spesifik ke scope lokal: using std::cout; membuat semua baris berikutnya boleh menulis cout tanpa awalan. Deklarasi ini dipakai per nama, sehingga kita tetap mengendalikan nama apa saja yang diangkat. Program berikut memakai dua deklarasi using dan sekaligus menunjukkan namespace buatan kita sendiri:
#include <iostream>
// Dua namespace berbeda boleh memakai nama yang sama tanpa tabrakan.
namespace toko {
const int HARGA_KIRIM = 15000;
}
namespace resto {
const int HARGA_KIRIM = 22000;
}
namespace format {
namespace dalam { // namespace bersarang
const int VERSI = 2;
}
}
int main() {
using std::cout; // deklarasi using tunggal
using toko::HARGA_KIRIM; // mengangkat satu nama spesifik
cout << "Biaya kirim toko : " << HARGA_KIRIM << "\n";
cout << "Biaya kirim resto : " << resto::HARGA_KIRIM << "\n";
cout << "Versi format : " << format::dalam::VERSI << "\n";
return 0;
}Output yang Dihasilkan:
Biaya kirim toko : 15000
Biaya kirim resto : 22000
Versi format : 2Mari kita bedah bagian yang baru:
- Baris 4-7 (
namespace toko): konstantaHARGA_KIRIMtinggal di dalam namespacetoko. Nama lengkapnya menjaditoko::HARGA_KIRIM. - Baris 9-12 (
namespace resto): namaHARGA_KIRIMyang sama dideklarasikan lagi, kali ini diresto. Kompiler tidak protes karena keduanya berada di kotak berbeda. - Baris 14-18 (
namespace format): namespacedalamdidefinisikan di dalamformat, menghasilkan jalur aksesformat::dalam::VERSI. - Baris 23-24 (deklarasi using):
coutdanHARGA_KIRIMmiliktokodiangkat ke dalammain(), sehingga baris 26 bisa menulis keduanya tanpa awalan. - Baris 27-28:
resto::HARGA_KIRIMtetap ditulis lengkap karena nama yang diangkat hanya versitoko— keduanya bisa hidup berdampingan dalam satu fungsi.
using namespace std: Kemudahan dan Risikonya #
Selain per nama, C++ menyediakan arahan using namespace std; yang mengangkat seluruh isi std sekaligus. Satu baris ini membuat cout, string, endl, dan ratusan nama lain langsung bisa dipakai tanpa awalan — itulah sebabnya banyak tutorial pemula membukanya dengan arahan ini. Kemudahan itu datang dengan harga yang perlu dipahami:
- Keuntungan: kode contoh dan program kecil menjadi ringkas; bagus untuk latihan cepat di satu file.
- Risiko: semua nama
stdberjatuhan ke namespace global kita, termasuk nama yang tidak kita kenal seperticount,swap, atausize. Ketika kode kita (atau pustaka yang dipasang) punya nama yang sama, compiler memunculkan pesanerror: reference to 'count' is ambiguousyang membingungkan pemula. - Aturan praktis: hindari
using namespace std;di dalam file header, karena semua file yang meng-include header itu ikut menanggung risikonya. Untuk file.cppmilik kita, keputusannya bebas — banyak tim memilih deklarasi per nama sebagai jalan tengah.
Namespace Bersarang dan Namespace Anonim #
Namespace boleh didefinisikan di dalam namespace lain (bersarang) seperti format::dalam pada contoh di atas, dan kedalamannya tidak dibatasi — meski dua sampai tiga level sudah jarang di kode nyata karena aksesnya makin panjang. C++17 memperkenalkan bentuk ringkas untuk nesting, namespace format::dalam { ... }, yang menulis satu level saja. Ada juga bentuk spesial bernama namespace anonim — namespace tanpa nama — yang isinya hanya dikenal di file tempat ia ditulis:
namespace {
// Nama di sini hanya terlihat oleh file ini (internal linkage),
// aman dari tabrakan dengan nama file lain saat dilink.
const int BATAS_INTERNAL = 100;
}Namespace anonim biasanya dipakai untuk detail implementasi internal sebuah file .cpp. Kegunaan penuhnya (dan istilah internal linkage) baru terasa saat program kita terdiri dari banyak file, yang dibahas pada Section Build System dan Project Structure. Untuk sekarang, cukup ingat polanya: namespace bernama untuk mengelompokkan, namespace anonim untuk menyembunyikan.
Dengan namespace, kita kini bisa membaca setiap std::... tanpa merasa asing. Babak berikutnya kita turun ke unit terkecil yang menyusun tubuh program: pernyataan (statement) dan ekspresi (expression) — dua istilah yang sering tertukar tetapi penting dibedakan sejak awal.