Pertimbangkan sepasang dua file sumber: file deklarasi antarmuka ( *.h
atau *.hpp
) dan file implementasinya ( *.cpp
).
Biarkan *.h
filenya seperti berikut:
namespace MyNamespace {
class MyClass {
public:
int foo();
};
}
Saya telah melihat dua praktik berbeda untuk menggunakan ruang nama di file sumber:
*.cpp
menunjukkan latihan # 1:
#include "MyClass.h"
using namespace MyNamespace;
int MyClass::foo() { ... }
*.cpp
menunjukkan latihan # 2:
#include "MyClass.h"
namespace MyNamespace {
int MyClass::foo() { ... }
}
Pertanyaan saya: Apakah ada perbedaan antara kedua praktik ini dan apakah yang satu dianggap lebih baik dari yang lain?
c++
namespaces
header-files
nickolay
sumber
sumber
int MyNamespace::MyClass::foo() ...
.Jawaban:
Dari sudut pandang keterbacaan kode, mungkin lebih baik menurut saya menggunakan metode # 2 karena alasan ini:
Anda dapat memiliki
using
beberapa ruang nama sekaligus, dan objek atau fungsi apa pun yang ditulis di bawah baris tersebut dapat termasuk dalam salah satu ruang nama tersebut (kecuali konflik penamaan). Membungkus seluruh file dalam satunamespace
blok lebih eksplisit, dan memungkinkan Anda untuk mendeklarasikan fungsi dan variabel baru yang termasuk dalam namespace tersebut dalam file .cpp juga.sumber
Yang paling jelas adalah opsi yang tidak Anda tampilkan:
int MyNamespace::MyClass::foo() { // ... }
Ini juga sangat bertele-tele; terlalu banyak bagi kebanyakan orang. Karena
using namespace
ini adalah resep untuk konflik nama, setidaknya menurut pengalaman saya, dan harus dihindari kecuali dalam cakupan dan tempat yang sangat terbatas, saya biasanya menggunakan # 2 Anda.sumber
Iya. # 1 dan # 2 masing-masing adalah contoh dari penggunaan-direktif dan definisi namespace . Mereka secara efektif sama dalam kasus ini tetapi memiliki konsekuensi lain. Misalnya, jika Anda memperkenalkan pengenal baru di sampingnya
MyClass::foo
, ini akan memiliki cakupan yang berbeda:# 1:
using namespace MyNamespace; int x; // defines ::x
# 2:
namespace MyNamespace { int x; // defines MyNamespace::x }
# 1 Kelebihan: sedikit lebih singkat; lebih sulit untuk secara tidak sengaja memasukkan sesuatu ke dalam
MyNamespace
tanpa disadari. Kekurangan: dapat menarik pengenal yang ada secara tidak sengaja.# 2 Kelebihan: lebih jelas bahwa definisi pengenal yang ada dan deklarasi pengenal baru milik keduanya
MyNamespace
. Kekurangan: lebih mudah untuk secara tidak sengaja memperkenalkan pengenalMyNamespace
.Kritik dari # 1 dan # 2 adalah bahwa mereka merujuk ke seluruh namespace ketika Anda mungkin hanya peduli tentang definisi anggota
MyNamespace::MyClass
. Ini berat dan tidak mengkomunikasikan maksudnya dengan baik.Alternatif yang mungkin untuk # 1 adalah menggunakan-deklarasi yang hanya menyertakan pengenal yang Anda minati:
#include "MyClass.h" using MyNamespace::MyClass; int MyClass::foo() { ... }
sumber
Saya juga ingin menambahkan bahwa jika Anda memutuskan karena alasan tertentu untuk mengimplementasikan spesialisasi template dalam file cpp dan hanya mengandalkan,
using namespace
Anda akan mengalami masalah berikut:// .h file namespace someNameSpace { template<typename T> class Demo { void foo(); }; } // .cpp file using namespace someNameSpace; template<typename T> void Demo<T>::foo(){} // this will produce // error: specialization of 'template<class T> void someNameSpace::Demo<T>::foo()' in different namespace [-fpermissive] template<> void Demo<int>::foo(){}
Jika tidak, jika Anda menerapkan metode # 2 ini akan baik-baik saja.
sumber
Saya ingin menambahkan satu cara lagi, menggunakan using-declaration :
#include "MyClass.h" using MyNamespace::MyClass; int MyClass::foo() { ... }
Dengan cara ini Anda tidak perlu mengetik nama namespace berkali-kali jika kelas memiliki banyak fungsi
sumber