Apa cakupan deklarasi "using" di C ++?


100

Saya menggunakan deklarasi 'using' di C ++ untuk menambahkan std :: string dan std :: vector ke namespace lokal (untuk menghemat pengetikan 'std ::' yang tidak perlu).

using std::string;
using std::vector;

class Foo { /*...*/ };

Apa ruang lingkup deklarasi ini? Jika saya melakukan ini di header, apakah itu akan menyuntikkan deklarasi 'menggunakan' ini ke dalam setiap file cpp yang menyertakan header?


18
Untuk berjaga-jaga jika tidak jelas dari jawaban lain di sini: - Jangan meletakkan usingdeklarasi (atau usingarahan) pada ruang lingkup file dalam file / header yang disertakan! Itu akan menyebabkan sakit kepala bagi pengguna header.
Michael Burr

Bahkan, jangan letakkan usingdeklarasi ( perintah fortiori ) di header sama sekali , bahkan di dalam namespace! Lihat cakupan penggunaan deklarasi dalam namespace untuk masalah yang disebabkannya.
Nils von Barth

@NilsvonBarth: Itu agak terlalu disederhanakan. Penggunaan usingdalam ruang lingkup kelas dan fungsi aman terkait masalah yang dibahas.
Sebastian Mach


Anda mungkin tertarik untuk membaca tentang fitur pencarian ADL C ++ .
Alexis Wilke

Jawaban:


59

Saat Anda #memasukkan file header di C ++, ini menempatkan seluruh konten file header ke tempat yang Anda sertakan di file sumber. Jadi menyertakan file yang memiliki usingdeklarasi memiliki efek yang sama persis dengan menempatkan usingdeklarasi di atas setiap file yang menyertakan file header tersebut.


51
... yang umumnya merupakan hal yang buruk.
Catskul

17
Tetapi jika Anda meletakkan usingdeklarasi di dalam a namespaceitu terbatas pada cakupan namespace itu, jadi secara umum OK (dengan peringatan biasa pada kebutuhan dan gaya khusus Anda).
Nol

1
... tetapi jika Anda menggunakan di dalam namespace, pastikan Anda tidak melakukannya untuk mencoba menyiasati sesuatu yang biasanya merupakan ide buruk, seperti Anda tidak dapat membungkus metode kelas yang dideklarasikan di luar namespace Y di dalam yang lain namespace X, agar Anda dapat menggunakan namespace X secara lokal. Itulah mengapa kami menggunakan namespace :: resolver terlebih dahulu. Jika masalah pengetikan sebesar itu, baik makro (yang dapat dengan mudah menyebabkan bau kode) atau lebih baik lagi, isolasi ke dalam sumbernya sendiri .cpp di mana Anda hanya akan menggunakan namespace di sana.
osirisgothra

1
Meskipun jawaban ini dan jawaban serupa adalah nasihat yang baik, mereka tidak menjawab pertanyaan itu.
Emile Cormier

116

Tidak ada yang istimewa tentang file header yang akan membuat usingdeklarasi tetap keluar. Ini adalah substitusi teks sederhana bahkan sebelum kompilasi dimulai.

Anda dapat membatasi usingdeklarasi ke lingkup:

void myFunction()
{
   using namespace std; // only applies to the function's scope
   vector<int> myVector;
}

12
Saya tidak pernah berpikir saya bisa menggunakannya di dalam suatu fungsi!
Agostino

1
Saya punya banyak namespace yang semuanya digunakan oleh satu file tipe "konglomerator", dan pengujian unit gmock sangat membosankan karena setiap pengujian menggunakan sesuatu dari namespace tertentu, dan saya pikir saya harus memenuhi syarat setiap variabel. Menggunakan usingfungsi di dalam (atau bahkan TESTmakro paling keren !) Membuat hidup saya jauh lebih baik!
dwanderson

54

Cakupan pernyataan using tergantung pada lokasinya di dalam kode:

  • Ditempatkan di bagian atas file, itu memiliki ruang lingkup di seluruh file itu.
  • Jika ini adalah file header, itu akan memiliki cakupan di semua file yang menyertakan header itu. Secara umum, ini " bukan ide yang baik " karena dapat memiliki efek samping yang tidak terduga
  • Jika tidak, pernyataan using memiliki ruang lingkup di dalam blok yang memuatnya mulai dari titik terjadinya hingga akhir blok. Jika ditempatkan dalam suatu metode, itu akan memiliki ruang lingkup dalam metode itu. Jika ditempatkan dalam definisi kelas itu akan memiliki ruang lingkup dalam kelas itu.

5
Saya pikir tidak mungkin menambahkan usingpernyataan dalam ruang lingkup kelas ...? Saya memiliki pertanyaan yang sama dengan OP karena itu karena saya ingin menghindari mengetik di std::semua tempat. Saya mendapat kelas yang menggunakan banyak vektor dengan petunjuk cerdas dan std::awalan lima karakter menambahkan banyak panjang baris - yang menurut saya terbaca lebih buruk. Jadi saya bertanya-tanya apakah usingdirektif dalam namespace yang berisi kelas itu ok? (Bahkan jika dalam sebuah header.)
thomthom

5
Bagaimana jika itu ditempatkan dalam lingkup a namespace { ... }?
einpoklum

Jadi Anda benar-benar dapat menulis: {using namespace blabla; kelas blah {}; } dan penggunaan itu hanya akan berlaku untuk kelas?
Dinaiz

8

Ruang lingkup adalah ruang lingkup apa pun tempat deklarasi menggunakan berada.

Jika ini lingkup global, maka lingkup global. Jika file berada dalam cakupan global file header, maka file tersebut akan berada dalam cakupan global setiap file sumber yang menyertakan header.

Jadi, saran umumnya adalah menghindari penggunaan deklarasi dalam cakupan global file header .


3
Itu tidak cukup kuat. Ganti menghindari dengan Jangan
Martin York

1
BUt menghindari lebih kuat dari tidak. "Hindari menabrak mobil lain"
bobobobo

6

Dalam kasus yang dikutip, file ("unit terjemahan"), yang berarti ya, setiap file yang menyertakannya.

Anda juga dapat meletakkan pernyataan using di dalam kelas, dalam hal ini, pernyataan tersebut berlaku hanya untuk kelas itu.

Secara umum, jika Anda perlu menentukan namespace di header, sering kali yang terbaik adalah memenuhi syarat sepenuhnya setiap pengenal yang diperlukan.


Perhatikan bahwa usingdeklarasi di kelas tidak berperilaku dengan cara yang sama seperti di luar kelas - misalnya Anda tidak dapat menggunakannya bring coutsebagai ganti std::coutke dalam cakupan kelas.
Nol

2

Itu betul. Ruang lingkup adalah modul yang menggunakan usingdeklarasi. Jika file header yang disertakan modul memiliki usingdeklarasi, cakupan deklarasi tersebut adalah modul tersebut, serta modul lain yang menyertakan header yang sama.


1

Ada beberapa komentar yang agak tidak memenuhi syarat ketika mereka mengatakan "Jangan". Itu terlalu keras, tetapi Anda harus mengerti kapan tidak apa-apa.

Menulis using std::stringtidak pernah OK. Menulis using ImplementationDetail::Foodi header Anda sendiri, saat header itu mendeklarasikan ImplementationDetail :: Foo tidak apa-apa, apalagi jika deklarasi using terjadi di namespace Anda. Misalnya

namespace MyNS {
    namespace ImplementationDetail {
        int Foo;
    }
    using ImplementationDetail::Foo;
}

1
Pengguna tajuk kemudian dapat menulisMyNS::Foo
Peter Remmers

Contoh yang lebih baik adalah using boost::posix_time::ptime. Tentu pengguna bisa menulis MyNS::ptimetapi itu bukan akhir dari dunia, dan mungkin diimbangi dengan kenyamanan bisa memiliki fungsi seperti MyFunction(ptime a, ptime b).
Nol

5
Mengapa adalah using std::stringtidak pernah ok? Bahkan di namespace Anda sendiri menyimpan banyak std::awalan?
thomthom

@thomthom tidak apa-apa jika dibungkus dalam lingkup seperti namespace Anda sendiri.
jcoffland
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.