Nếu bạn đang sử dụng thư viện chuẩn rất nhiều, hãy nhập std :: trước khi mọi thứ bạn sử dụng từ thư viện chuẩn có thể trở nên lặp lại. C ++ cung cấp một số lựa chọn thay thế để đơn giản hóa mọi thứ, được gọi là sử dụng câu lệnh.
Nội dung chính
1. Sử dụng khai báo
Một cách để đơn giản hóa mọi thứ là sử dụng câu lệnh using.
Đây là chương trình Hello world của chúng ta, với câu lệnh sử dụng ở dòng 5:
#include <iostream>
int main()
{
using std::cout; // this using declaration tells the compiler that cout should resolve to std::cout
cout << "Hello world!"; // so no std:: prefix is needed here!
return 0;
} // the using declaration expires here
Khai báo using std :: cout; nói với trình biên dịch rằng chúng ta sẽ sử dụng cout đối tượng từ namaspace std. Vì vậy, bất cứ khi nào nó nhìn thấy cout, nó sẽ cho rằng chúng ta có nghĩa là std :: cout. Nếu có xung đột đặt tên giữa std :: cout và một số cách sử dụng cout khác, std :: cout sẽ được ưu tiên hơn. Do đó, ở dòng 6, chúng ta có thể gõ cout thay vì std :: cout.
Điều này không giúp tiết kiệm nhiều nỗ lực trong ví dụ đơn giản này, nhưng nếu bạn đang sử dụng cout nhiều lần bên trong một hàm, khai báo đang sử dụng có thể làm cho mã của bạn dễ đọc hơn. Lưu ý rằng bạn sẽ cần một khai báo sử dụng riêng cho từng tên bạn sử dụng (ví dụ: một cho std :: cout, một cho std :: cin, v.v.).
Mặc dù phương pháp này ít rõ ràng hơn so với việc sử dụng tiền tố std ::, nhưng nó thường được coi là an toàn và có thể chấp nhận được (khi được sử dụng bên trong một hàm).
2. Sử dụng Chỉ thị
Một cách khác để đơn giản hóa mọi thứ là sử dụng câu lệnh using. Đây là chương trình Hello world của chúng tôi một lần nữa, với chỉ thị sử dụng trên dòng 5:
#include <iostream>
int main()
{
using namespace std; // this using directive tells the compiler that we're using everything in the std namespace!
cout << "Hello world!"; // so no std:: prefix is needed here!
return 0;
}
Lệnh using using namespace std; nói với trình biên dịch rằng chúng ta muốn sử dụng mọi thứ trong không gian tên std, vì vậy nếu trình biên dịch tìm thấy tên mà nó không nhận ra, nó sẽ kiểm tra không gian tên std. Do đó, khi trình biên dịch gặp cout (mà nó sẽ không nhận ra), nó sẽ tìm kiếm trong không gian tên std và tìm thấy nó ở đó. Nếu có xung đột đặt tên giữa std :: cout và một số cách sử dụng khác của cout, trình biên dịch sẽ gắn cờ đó là lỗi (thay vì thích một trường hợp hơn trường kia).
Để có mục đích minh họa, hãy xem một ví dụ trong đó một lệnh using gây ra sự mơ hồ:
#include <iostream>
namespace a
{
int x{ 10 };
}
namespace b
{
int x{ 20 };
}
int main()
{
using namespace a;
using namespace b;
std::cout << x << '\n';
return 0;
}
Trong ví dụ trên, trình biên dịch không thể xác định xem x trong hàm chính tham chiếu đến a :: x hay b :: x. Trong trường hợp này, nó sẽ không biên dịch được với lỗi “ký hiệu không rõ ràng”. Chúng ta có thể giải quyết vấn đề này bằng cách loại bỏ một trong các câu lệnh using hoặc sử dụng tiền tố a :: hoặc b :: rõ ràng với biến x.
Đây là một ví dụ khác tinh tế hơn:
#include <iostream> // imports the declaration of std::cout
int cout() // declares our own "cout" function
{
return 5;
}
int main()
{
using namespace std; // makes std::cout accessible as "cout"
cout << "Hello, world!"; // uh oh! Which cout do we want here? The one in the std namespace or the one we defined above?
return 0;
}
Trong ví dụ trên, trình biên dịch không thể xác định việc chúng ta sử dụng cout có nghĩa là std :: cout hay hàm cout mà chúng ta đã xác định hay không và một lần nữa sẽ không biên dịch được với lỗi “ký hiệu không rõ ràng”. Mặc dù ví dụ này là tầm thường, nếu chúng ta đã đặt tiền tố std :: cout một cách rõ ràng như thế này:
std::cout << "Hello, world!"; // tell the compiler we mean std::cout
hoặc sử dụng một khai báo using thay vì một chỉ thị using:
using std::cout; // tell the compiler that cout means std::cout
cout << "Hello, world!"; // so this means std::cout
thì chương trình của chúng ta sẽ không có bất kỳ vấn đề nào ngay từ đầu.
3. Giới hạn phạm vi sử dụng các khai báo và chỉ thị
Nếu một khai báo using hoặc chỉ thị using được sử dụng trong một khối, thì câu lệnh using chỉ áp dụng trong khối đó (nó tuân theo các quy tắc xác định phạm vi khối thông thường). Đây là một điều tốt, vì nó làm giảm khả năng xảy ra đặt tên trùng ngay trong khối đó. Tuy nhiên, nhiều lập trình viên mới đưa việc sử dụng các chỉ thị vào phạm vi toàn cầu. Điều này kéo tất cả các tên từ không gian tên trực tiếp vào phạm vi toàn cục, làm tăng đáng kể cơ hội xảy ra va chạm đặt tên (xem bài – Đặt tên trùng nhau và giới thiệu về không gian tên để biết thêm thông tin về điều này).
Bạn nên
Mặc dù nhiều sách giáo khoa và hướng dẫn sử dụng chúng một cách tự do, nhưng hãy tránh sử dụng hoàn toàn các chỉ thị. Sử dụng các khai báo có thể sử dụng bên trong các khối, nơi tác động của chúng bị hạn chế, nhưng không phải trong phạm vi toàn cầu.
4. Hủy hoặc thay thế một câu lệnh using
Khi một câu lệnh using đã được khai báo, không có cách nào để hủy bỏ hoặc thay thế nó bằng một câu lệnh using khác trong phạm vi mà nó đã được khai báo.
int main()
{
using namespace Foo;
// there's no way to cancel the "using namespace Foo" here!
// there's also no way to replace "using namespace Foo" with a different using statement
return 0;
} // using namespace Foo ends here
Điều tốt nhất bạn có thể làm là cố ý giới hạn phạm vi của câu lệnh using ngay từ đầu bằng cách sử dụng các quy tắc phạm vi của khối.
/*
Cafedev.vn - Kênh thông tin IT hàng đầu Việt Nam
@author cafedevn
Contact: cafedevn@gmail.com
Fanpage: https://www.facebook.com/cafedevn
Group: https://www.facebook.com/groups/cafedev.vn/
Instagram: https://instagram.com/cafedevn
Twitter: https://twitter.com/CafedeVn
Linkedin: https://www.linkedin.com/in/cafe-dev-407054199/
Pinterest: https://www.pinterest.com/cafedevvn/
YouTube: https://www.youtube.com/channel/UCE7zpY_SlHGEgo67pHxqIoA/
*/
int main()
{
{
using namespace Foo;
// calls to Foo:: stuff here
} // using namespace Foo expires
{
using namespace Goo;
// calls to Goo:: stuff here
} // using namespace Goo expires
return 0;
}
Tất nhiên, tất cả những vấn đề đau đầu này có thể tránh được bằng cách sử dụng toán tử phân giải phạm vi (: 🙂 ngay từ đầu.
Cài ứng dụng cafedev để dễ dàng cập nhật tin và học lập trình mọi lúc mọi nơi tại đây.
Nguồn và Tài liệu tiếng anh tham khảo:
Tài liệu từ cafedev:
- Full series tự học C++ từ cơ bản tới nâng cao tại đây nha.
- Ebook về C++ tại đây.
- Các series tự học lập trình MIỄN PHÍ khác
- Nơi liên hệ hợp tác hoặc quảng cáo cùng Cafedevn tại đây.
Nếu bạn thấy hay và hữu ích, bạn có thể tham gia các kênh sau của cafedev để nhận được nhiều hơn nữa:
Chào thân ái và quyết thắng!