Có cách nào tốt hơn để thể hiện các không gian tên lồng nhau trong C ++ trong tiêu đề không


97

Tôi đã chuyển từ C ++ sang Java và C # và nghĩ rằng việc sử dụng không gian tên / gói ở đó tốt hơn nhiều (có cấu trúc tốt). Sau đó, tôi quay lại C ++ và cố gắng sử dụng không gian tên theo cách tương tự nhưng cú pháp yêu cầu rất khủng khiếp trong tệp tiêu đề.

namespace MyCompany
{
    namespace MyModule
    {
        namespace MyModulePart //e.g. Input
        {
            namespace MySubModulePart
            {
                namespace ...
                {
                    public class MyClass    

Điều sau có vẻ lạ đối với tôi (để tránh thụt lề sâu):

namespace MyCompany
{
namespace MyModule
{
namespace MyModulePart //e.g. Input
{
namespace MySubModulePart
{
namespace ...
{
     public class MyClass
     {

Có cách nào ngắn hơn để diễn đạt điều trên không? Tôi đang thiếu một cái gì đó như

namespace MyCompany::MyModule::MyModulePart::...
{
   public class MyClass

Cập nhật

Ok, một số người nói rằng khái niệm sử dụng trong Java / C # và C ++ là khác nhau. Có thật không? Tôi nghĩ rằng tải lớp (động) không phải là mục đích duy nhất cho không gian tên (đây là một quan điểm lý luận rất kỹ thuật). Tại sao tôi không nên sử dụng nó để dễ đọc và cấu trúc, ví dụ: hãy nghĩ đến "IntelliSense".

Hiện tại, không có logic / keo dán giữa không gian tên và những gì bạn có thể tìm thấy ở đó. Java và C # làm điều này tốt hơn nhiều ... Tại sao bao gồm <iostream>và có không gian tên std? Được rồi, nếu bạn nói logic nên dựa vào tiêu đề để bao gồm, tại sao #include không sử dụng cú pháp thân thiện "IntelliSense" như #include <std::io::stream>hoặc <std/io/stream>? Tôi nghĩ rằng việc thiếu cấu trúc trong libs mặc định là một điểm yếu của C ++ so với Java / C #.

Nếu tính duy nhất đối với các xung đột khao khát là một Điểm (cũng là một điểm của C # và Java) thì một ý tưởng hay là sử dụng tên dự án hoặc tên công ty làm không gian tên, bạn có nghĩ vậy không?

Một mặt người ta nói C ++ là linh hoạt nhất ... nhưng mọi người đều nói "đừng làm điều này"? Đối với tôi, có vẻ như C ++ có thể làm được nhiều thứ nhưng có một cú pháp khủng khiếp ngay cả đối với những thứ dễ dàng nhất trong nhiều trường hợp so với C #.

Cập nhật 2

Hầu hết người dùng nói rằng việc tạo lồng ghép sâu hơn hai Cấp độ là vô nghĩa. Ok, vậy còn Windows :: UI :: Xaml và Windows :: UI :: Xaml :: Controls :: Các không gian tên nguyên thủy trong phát triển Win8 thì sao? Tôi nghĩ việc sử dụng không gian tên của Microsoft có ý nghĩa và nó thực sự sâu sắc hơn chỉ là 2 Cấp. Tôi nghĩ rằng các thư viện / dự án lớn hơn cần lồng ghép sâu hơn (tôi ghét các tên lớp như ExtraLongClassNameBecauseEveryThingIsInTheSameNameSpace ... thì bạn cũng có thể đặt mọi thứ vào không gian tên chung).

Cập nhật 3 - Kết luận

Hầu hết nói "không làm điều đó", nhưng ... thậm chí tăng có một lồng sâu hơn sau đó một hoặc hai cấp độ. Đúng, nó là một thư viện nhưng: Nếu bạn muốn mã có thể sử dụng lại - hãy coi mã của chính bạn như một thư viện mà bạn sẽ cung cấp cho người khác. Tôi cũng sử dụng lồng sâu hơn cho mục đích khám phá bằng cách sử dụng không gian tên.


3
Nó có phải là lạm dụng namespacetừ khóa không?
Nawaz

4
không gian tên và hệ thống mô-đun c # / java không phục vụ cùng một mục đích, vì vậy bạn không nên cố gắng sử dụng chúng theo cùng một cách. và không, không có cú pháp nào đơn giản hơn, chỉ đơn giản vì không có ý nghĩa gì khi cung cấp một cú pháp để làm cho mọi thứ dễ dàng hơn, điều đó không có nghĩa là để làm.
PlasmaHH

@PlasmaHH ... vậy điểm yếu là thiếu cấu trúc của std lib của C ++? (xem ví dụ đơn giản của tôi trong bản cập nhật)
Beachwalker

@Stegi: Nếu bạn có thể đưa ra các lý lẽ xác đáng tại sao nó bị thiếu và những lợi ích vững chắc nào chúng ta sẽ nhận được từ việc cấu trúc hóa như vậy, chúng ta có thể nói về những điểm yếu tiềm ẩn. Cho đến lúc đó, tôi sẽ gọi jav vô tận lồng các gói là khó hiểu nhất.
PlasmaHH

3
@PlasmaHH Intellisense và các trình trợ giúp khác để đưa / vào tiêu đề (gói) sau. Các dự án lớn trong một công ty có thể cần nhiều hơn một lồng nhau (ví dụ: vw :: golflib :: io) để có một tuyên bố rõ ràng về không gian tên chứa "phạm vi" nào. Chà, bạn chỉ có thể sử dụng vw :: nhưng nếu không gian tên được sử dụng để tránh đụng độ, tại sao lại khai báo quá khủng khiếp? Điều này dẫn đến việc không ai sử dụng nó hoặc chỉ sử dụng không gian tên với độ sâu là một (như gợi ý thường thấy).
Beachwalker

Câu trả lời:


130

C ++ 17 có thể đơn giản hóa định nghĩa không gian tên lồng nhau:

namespace A::B::C {
}

tương đương với

namespace A { namespace B { namespace C {
} } }

Xem (8) trên trang không gian tên trên cppreference:
http://en.cppreference.com/w/cpp/language/namespace


4
... được kích hoạt bởi công tắc trình biên dịch/std:c++latest
sunny moon

3
Lưu ý rằng nếu bạn sẽ sử dụng /std:c++latesttrong Visual Studio 2015 và cũng sử dụng Boost, bạn có thể gặp phải lỗi trình biên dịch rất khó hiểu khi bạn bao gồm một số tiêu đề Boost. Tôi phải đối mặt với vấn đề này như mô tả trong câu hỏi StackOverflow này
Vivit

1
Nó hoạt động như hiện tại, không gian tên A :: B :: C. Tôi đã thử nghiệm với g ++ - 6.0
ervinbosenbacher


17

Tôi hoàn toàn ủng hộ câu trả lời của peterchen nhưng muốn thêm điều gì đó giải quyết một phần khác của câu hỏi của bạn.

Khai báo không gian tên là một trong những trường hợp rất hiếm trong C ++ mà tôi thực sự thích sử dụng #defines.

#define MY_COMPANY_BEGIN  namespace MyCompany { // begin of the MyCompany namespace
#define MY_COMPANY_END    }                     // end of the MyCompany namespace
#define MY_LIBRARY_BEGIN  namespace MyLibrary { // begin of the MyLibrary namespace
#define MY_LIBRARY_END    }                     // end of the MyLibrary namespace

Điều này cũng loại bỏ nhu cầu nhận xét gần dấu ngoặc nhọn đóng của không gian tên (Bạn đã bao giờ cuộn xuống cuối tệp nguồn lớn và cố gắng thêm / xóa / cân bằng dấu ngoặc nhọn bị thiếu nhận xét về dấu ngoặc nhọn đóng phạm vi nào chưa? Không vui .).

MY_COMPANY_BEGIN
MY_LIBRARY_BEGIN

class X { };

class Y { };

MY_LIBRARY_END
MY_COMPANY_END

Nếu bạn muốn đặt tất cả các khai báo không gian tên trên một dòng duy nhất, bạn cũng có thể làm điều đó với một chút phép thuật tiền xử lý (khá xấu xí):

// helper macros for variadic macro overloading
#define VA_HELPER_EXPAND(_X)                    _X  // workaround for Visual Studio
#define VA_COUNT_HELPER(_1, _2, _3, _4, _5, _6, _Count, ...) _Count
#define VA_COUNT(...)                           VA_HELPER_EXPAND(VA_COUNT_HELPER(__VA_ARGS__, 6, 5, 4, 3, 2, 1))
#define VA_SELECT_CAT(_Name, _Count, ...)       VA_HELPER_EXPAND(_Name##_Count(__VA_ARGS__))
#define VA_SELECT_HELPER(_Name, _Count, ...)    VA_SELECT_CAT(_Name, _Count, __VA_ARGS__)
#define VA_SELECT(_Name, ...)                   VA_SELECT_HELPER(_Name, VA_COUNT(__VA_ARGS__), __VA_ARGS__)

// overloads for NAMESPACE_BEGIN
#define NAMESPACE_BEGIN_HELPER1(_Ns1)             namespace _Ns1 {
#define NAMESPACE_BEGIN_HELPER2(_Ns1, _Ns2)       namespace _Ns1 { NAMESPACE_BEGIN_HELPER1(_Ns2)
#define NAMESPACE_BEGIN_HELPER3(_Ns1, _Ns2, _Ns3) namespace _Ns1 { NAMESPACE_BEGIN_HELPER2(_Ns2, _Ns3)

// overloads for NAMESPACE_END
#define NAMESPACE_END_HELPER1(_Ns1)               }
#define NAMESPACE_END_HELPER2(_Ns1, _Ns2)         } NAMESPACE_END_HELPER1(_Ns2)
#define NAMESPACE_END_HELPER3(_Ns1, _Ns2, _Ns3)   } NAMESPACE_END_HELPER2(_Ns2, _Ns3)

// final macros
#define NAMESPACE_BEGIN(_Namespace, ...)    VA_SELECT(NAMESPACE_BEGIN_HELPER, _Namespace, __VA_ARGS__)
#define NAMESPACE_END(_Namespace, ...)      VA_SELECT(NAMESPACE_END_HELPER,   _Namespace, __VA_ARGS__)

Bây giờ bạn có thể làm điều này:

NAMESPACE_BEGIN(Foo, Bar, Baz)

class X { };

NAMESPACE_END(Baz, Bar, Foo) // order doesn't matter, NAMESPACE_END(a, b, c) would work equally well

Foo::Bar::Baz::X x;

Để lồng sâu hơn ba cấp, bạn sẽ phải thêm macro trợ giúp lên đến số lượng mong muốn.


Dù không thích #definenhưng tôi khá ấn tượng về phép thuật tiền xử lý đó ... chỉ khi tôi không phải thêm macro trợ giúp bổ sung để lồng sâu hơn ... à, dù sao thì tôi cũng sẽ không sử dụng nó nên .. .
galdin

12

Không gian tên C ++ được sử dụng để nhóm các giao diện, không phải để phân chia các thành phần hoặc thể hiện sự phân chia chính trị.

Tiêu chuẩn này đã cố gắng cấm sử dụng không gian tên giống như Java. Ví dụ, bí danh không gian tên cung cấp một cách để dễ dàng sử dụng các tên không gian tên dài hoặc lồng nhau sâu.

namespace a {
namespace b {
namespace c {}
}
}

namespace nsc = a::b::c;

Nhưng namespace nsc {}sau đó sẽ là một lỗi, vì một vùng tên chỉ có thể được xác định bằng cách sử dụng tên-không gian tên-ban đầu của nó . Về cơ bản, tiêu chuẩn làm cho mọi thứ trở nên dễ dàng đối với người sử dụng thư viện như vậy nhưng khó đối với người triển khai . Điều này không khuyến khích mọi người viết những thứ như vậy nhưng sẽ giảm bớt ảnh hưởng nếu họ viết.

Bạn nên có một không gian tên cho mỗi giao diện được xác định bởi một tập hợp các lớp và chức năng liên quan. Các giao diện phụ nội bộ hoặc tùy chọn có thể đi vào các không gian tên lồng nhau. Nhưng sâu hơn hai cấp độ nên là một lá cờ đỏ rất nghiêm trọng.

Cân nhắc sử dụng các ký tự gạch dưới và tiền tố nhận dạng khi ::không cần toán tử.


16
Ok, vậy còn Windows :: UI :: Xaml và Windows :: UI :: Xaml :: Controls :: Các không gian tên nguyên thủy trong phát triển Win8 thì sao? Tôi nghĩ việc sử dụng không gian tên của Microsoft có ý nghĩa và nó thực sự sâu sắc hơn chỉ là 2 Cấp.
Beachwalker vào

2
Sử dụng ít hơn 2 cấp độ là một lá cờ đỏ và sử dụng 3 hoặc 4 là hoàn toàn ổn. Cố gắng đạt được một hệ thống phân cấp không gian tên phẳng khi nó không hợp lý sẽ làm mất đi mục đích của không gian tên - tránh xung đột tên. Tôi đồng ý rằng bạn nên có một cấp cho giao diện và một cấp khác cho các giao diện con và nội bộ. Nhưng xung quanh đó, bạn cần ít nhất một cấp nữa cho không gian tên công ty (đối với các công ty vừa và nhỏ) hoặc hai cấp cho công ty và bộ phận (đối với các công ty lớn). Nếu không gian tên giao diện của bạn sẽ đụng độ với những người từ các giao diện khác có cùng tên được phát triển ở nơi khác
Kaiserludi

@Kaiserludi Ưu điểm kỹ thuật của company::divisionover là company_divisiongì?
Potatoswatter

@Potatoswatter Bên trong công ty :: anotherDivsion, bạn chỉ có thể sử dụng 'bộ phận' ngắn hơn. để tham chiếu đến company :: phân chia ngay cả trong tiêu đề nơi bạn nên tránh làm ô nhiễm không gian tên cấp cao hơn bằng cách sử dụng 'sử dụng không gian tên'. Bên ngoài không gian tên công ty, bạn vẫn có thể thực hiện 'sử dụng công ty không gian tên;' khi các tên bộ phận không xung đột với bất kỳ không gian tên nào khác trong phạm vi của bạn, nhưng khi các tên giao diện bên trong một số không gian tên bộ phận xung đột khiến bạn không thể thực hiện 'sử dụng không gian tên company_division;'.
Kaiserludi

3
@Potatoswatter Vấn đề là bạn nhận được nó thực tế miễn phí (company :: Division không lâu hơn company_division) và không phải xác định bí danh không gian tên phụ trước để sử dụng nó.
Kaiserludi

6

Không, và xin đừng làm vậy.

Mục đích của không gian tên chủ yếu là giải quyết xung đột trong không gian tên chung.

Mục đích phụ là viết tắt địa phương của các ký hiệu; ví dụ: một UpdateUIphương pháp phức tạp có thể sử dụng một using namespace WndUIđể sử dụng các ký hiệu ngắn hơn.

Tôi đang tham gia một dự án 1.3MLoc và không gian tên duy nhất mà chúng tôi có là:

  • đã nhập thư viện COM bên ngoài (chủ yếu để cô lập xung đột tiêu đề giữa #import#include windows.h)
  • Một cấp không gian tên "API công khai" cho các khía cạnh nhất định (giao diện người dùng, quyền truy cập DB, v.v.)
  • Không gian tên "Chi tiết triển khai" không phải là một phần của API công khai (không gian tên ẩn danh trong .cpp hoặc ModuleDetailHereBeTygerskhông gian tên trong lib chỉ tiêu đề)
  • enums là vấn đề lớn nhất trong kinh nghiệm của tôi. Họ gây ô nhiễm như điên.
  • Tôi vẫn cảm thấy nó hoàn toàn có quá nhiều không gian tên

Trong dự án này, tên lớp, v.v. sử dụng mã "vùng" gồm hai hoặc ba chữ cái (ví dụ: CDBNodethay vì DB::CNode). Nếu bạn thích cái sau hơn, có chỗ cho không gian tên "công khai" cấp thứ hai, nhưng không còn nữa.

Các enum dành riêng cho từng lớp, v.v. có thể là thành viên của các lớp đó (mặc dù tôi đồng ý rằng điều này không phải lúc nào cũng tốt và đôi khi rất khó để nói liệu bạn có nên hay không)

Cũng hiếm khi cần đến không gian tên "công ty", ngoại trừ nếu bạn đang gặp vấn đề lớn với các thư viện của bên thứ 3 được phân phối dưới dạng tệp nhị phân, không cung cấp không gian tên riêng của chúng và không thể dễ dàng đưa vào một (ví dụ: trong tệp nhị phân phân phối). Tuy nhiên, theo kinh nghiệm của tôi, buộc chúng vào một không gian tên dễ thực hiện hơn nhiều.


[sửa] Theo câu hỏi tiếp theo của Stegi:

Ok, vậy còn Windows :: UI :: Xaml và Windows :: UI :: Xaml :: Controls :: Các không gian tên nguyên thủy trong phát triển Win8 thì sao? Tôi nghĩ việc sử dụng không gian tên của Microsoft có ý nghĩa và nó thực sự sâu sắc hơn chỉ 2 Cấp

Xin lỗi nếu tôi không đủ rõ ràng: Hai cấp độ không phải là một giới hạn khó và hơn thế nữa không phải là xấu về bản chất. Tôi chỉ muốn chỉ ra rằng bạn hiếm khi cần nhiều hơn hai, theo kinh nghiệm của tôi, ngay cả trên một cơ sở mã lớn. Làm tổ sâu hơn hoặc nông hơn là một sự đánh đổi.

Bây giờ, trường hợp của Microsoft được cho là khác. Có lẽ là một nhóm lớn hơn nhiều và tất cả mã là thư viện.

Tôi cho rằng Microsoft đang bắt chước thành công của Thư viện .NET ở đây, nơi không gian tên góp phần vào khả năng khám phá của thư viện mở rộng. (.NET có khoảng 18000 kiểu.)

Tôi giả định thêm rằng có một ký hiệu (thứ tự độ lớn) tối ưu trong một không gian tên. nói, 1 không có ý nghĩa, 100 âm thanh đúng, 10000 rõ ràng là nhiều.


TL; DR: Đó là một sự đánh đổi và chúng tôi không có những con số khó. Chơi an toàn, đừng lạm dụng theo bất kỳ hướng nào. "Đừng làm điều đó" chỉ xuất phát từ câu "Bạn có vấn đề với điều đó, tôi có vấn đề với điều đó và tôi không thấy lý do tại sao bạn cần nó."


7
Ok, vậy còn Windows :: UI :: Xaml và Windows :: UI :: Xaml :: Controls :: Các không gian tên nguyên thủy trong phát triển Win8 thì sao? Tôi nghĩ việc sử dụng không gian tên của Microsoft có ý nghĩa và nó thực sự sâu sắc hơn chỉ là 2 Cấp.
Beachwalker vào

2
Nếu tôi cần các hằng số truy cập toàn cục, tôi muốn đặt chúng trong một không gian tên với tên như thế nào Constants, sau đó tạo các không gian tên lồng nhau với các tên thích hợp để phân loại các hằng số; nếu cần, sau đó tôi sử dụng các không gian tên khác để tránh xung đột tên. Không Constantsgian tên này chính nó được chứa trong một không gian tên bắt tất cả cho mã hệ thống của chương trình, với tên chẳng hạn SysData. Điều này tạo ra một tên đầy đủ có chứa ba hoặc bốn không gian tên (ví dụ như SysData::Constants::ErrorMessages, SysData::Constants::Ailments::Bitflagshoặc SysData::Defaults::Engine::TextSystem).
Justin Time - Phục hồi Monica

1
Khi các hằng số được yêu cầu trong mã thực tế, bất kỳ hàm nào cần chúng sẽ sử dụng một usingchỉ thị để đưa vào các tên thích hợp, giảm thiểu khả năng xảy ra các tên xung đột. Tôi thấy nó cải thiện khả năng đọc và giúp ghi lại bất kỳ sự phụ thuộc nào của khối mã nhất định. Ngoài hằng số, tôi có xu hướng thử và giữ nó ở hai không gian tên nếu có thể (chẳng hạn như SysData::ExceptionsSysData::Classes).
Justin Time - Phục hồi Monica

2
Nói chung, tôi muốn nói rằng trong các trường hợp chung, tốt nhất là sử dụng một số lượng tối thiểu các không gian tên lồng nhau, nhưng nếu bạn cần các đối tượng toàn cục vì lý do nào đó (cho dù là hằng số hay có thể thay đổi, tốt nhất là trước đây), nhiều không gian tên lồng nhau nên được sử dụng để tách chúng thành các danh mục thích hợp, vừa để ghi lại việc sử dụng chúng và giảm thiểu các xung đột tên có thể xảy ra.
Justin Time - Phục hồi Monica

2
-1 cho "vui lòng không làm điều này" mà không có lý do khách quan tại sao (mặc dù đã làm rõ sau đó). Ngôn ngữ hỗ trợ các không gian tên lồng nhau và một dự án có thể có lý do chính đáng để sử dụng chúng. Một cuộc thảo luận về những lý do có thể xảy ra như vậy và bất kỳ nhược điểm cụ thể, khách quan nào khi làm như vậy sẽ đảo ngược sự phản đối của tôi.
TypeIA,

4

Đây là trích dẫn từ tài liệu Lzz (Lazy C ++):

Lzz nhận ra các cấu trúc C ++ sau:

định nghĩa không gian tên

Một không gian tên chưa được đặt tên và tất cả các khai báo kèm theo được xuất ra tệp nguồn. Quy tắc này ghi đè tất cả các quy tắc khác.

Tên của một không gian tên được đặt tên có thể đủ điều kiện.

   namespace A::B { typedef int I; }

tương đương với:

   namespace A { namespace B { typedef int I; } }

Tất nhiên chất lượng của các nguồn phụ thuộc vào các công cụ như vậy là điều còn tranh cãi ... Tôi muốn nói rằng đó là một sự tò mò, cho thấy rằng căn bệnh cú pháp do C ++ gây ra có thể có nhiều dạng (tôi cũng có ...)


2

Cả hai tiêu chuẩn (C ++ 2003 và C ++ 11) đều rất rõ ràng rằng tên của không gian tên là một định danh. Điều này có nghĩa là các tiêu đề lồng nhau rõ ràng là bắt buộc.

Ấn tượng của tôi rằng đây không phải là một vấn đề lớn để cho phép đặt số nhận dạng đủ điều kiện bên cạnh một tên đơn giản của không gian tên, nhưng vì một số lý do, điều này không được phép.


1

Bạn có thể sử dụng cú pháp này:

namespace MyCompany {
  namespace MyModule {
    namespace MyModulePart //e.g. Input {
      namespace MySubModulePart {
        namespace ... {
          class MyClass;
        }
      }
    }
  }
}

// Here is where the magic happens
class MyCompany::MyModule::MyModulePart::MySubModulePart::MyYouGetTheIdeaModule::MyClass {
    ...
};

Lưu ý rằng cú pháp này hợp lệ ngay cả trong C ++ 98 và nó gần giống với những gì hiện có trong C ++ 17 với các định nghĩa không gian tên lồng nhau .

Chúc các bạn vui vẻ!

Nguồn:


Đó là sytax được đề cập trong câu hỏi thay vào đó tìm kiếm giải pháp tốt hơn. Bây giờ, với C ++ 17 là một giải pháp thay thế hợp lệ có sẵn như đã nêu trong câu trả lời được chấp nhận. Xin lỗi, phản đối vì không đọc câu hỏi và câu trả lời.
Beachwalker

@Beachwalker, đừng để bị bắt kịp cú pháp. Khai báo không gian tên ở trên cũng có thể giống như trong câu trả lời được chấp nhận. Điểm chính mà tôi muốn nhấn mạnh bằng câu trả lời này là những gì OP đã nói rằng ông ấy đã bỏ lỡ, và những gì tôi đã làm bên dưới mớ hỗn độn không gian tên đó. Theo như tôi có thể thấy mọi người dường như đã tập trung vào việc khai báo mọi thứ trong không gian tên, trong khi câu trả lời của tôi đưa bạn ra khỏi mớ hỗn độn lồng nhau và tôi chắc chắn OP sẽ đánh giá cao cú pháp này nếu có ai đó đã đề cập đến nó 4 năm trước khi câu hỏi này lần đầu tiên được hỏi.
smac89

1

Bài báo này bao gồm chủ đề khá tốt: Giấy không gian tên

Về cơ bản, điều này tóm tắt lại. Các không gian tên của bạn càng dài thì khả năng mọi người sử dụng using namespacechỉ thị càng cao.

Vì vậy, nhìn vào đoạn mã sau, bạn có thể thấy một ví dụ mà điều này sẽ gây hại cho bạn:

namespace abc { namespace testing {
    class myClass {};
}}

namespace def { namespace testing {
    class defClass { };
}}

using namespace abc;
//using namespace def;

int main(int, char**) {
    testing::myClass classInit{};
}

Mã này sẽ biên dịch tốt, tuy nhiên, nếu bạn bỏ ghi chú dòng //using namespace def;thì không gian tên "thử nghiệm" sẽ trở nên mơ hồ và bạn sẽ có xung đột đặt tên. Điều này có nghĩa là cơ sở mã của bạn có thể đi từ ổn định đến không ổn định bằng cách đưa vào thư viện của bên thứ ba.

Trong C #, ngay cả khi bạn đã sử dụng using abc;using def;trình biên dịch có thể nhận ra điều đó testing::myClasshoặc thậm chí chỉ myClasslà trong abc::testingkhông gian tên, nhưng C ++ sẽ không nhận ra điều này và nó được phát hiện là xung đột.


0

Có, bạn sẽ phải làm như thế

namespace A{ 
namespace B{
namespace C{} 
} 
}

Tuy nhiên, bạn đang cố gắng sử dụng không gian tên theo cách mà chúng không được sử dụng. Kiểm tra câu hỏi này , có thể bạn sẽ thấy nó hữu ích.


-1

[CHỈNH SỬA:]
Vì không gian tên lồng nhau c ++ 17 được hỗ trợ như một tính năng ngôn ngữ chuẩn ( https://en.wikipedia.org/wiki/C%2B%2B17 ). Hiện tại, tính năng này không được hỗ trợ trong g ++ 8, nhưng nó có thể được tìm thấy trong trình biên dịch clang ++ 6.0.


[KẾT LUẬN:]
Sử dụng clang++6.0 -std=c++17làm lệnh biên dịch mặc định của bạn. Sau đó, mọi thứ sẽ hoạt động tốt - và bạn sẽ có thể biên dịch namespace OuterNS::InnerNS1::InnerNS2 { ... }trong các tệp của mình.


[CÂU TRẢ LỜI GỐC:]
Vì câu hỏi này hơi cũ, tôi sẽ cho rằng bạn đã chuyển sang câu hỏi. Nhưng đối với những người khác, những người vẫn đang tìm kiếm câu trả lời, tôi đã nảy ra ý tưởng sau:

Bộ đệm Emacs hiển thị tệp chính, tệp không gian tên, lệnh / kết quả biên dịch và thực thi dòng lệnh.

(Tôi có thể tạo quảng cáo cho Emacs ở đây không :)?) Đăng một hình ảnh dễ dàng hơn nhiều và dễ đọc hơn là chỉ đăng mã. Tôi không có ý định cung cấp một máy nướng đầy đủ tất cả các trường hợp góc, đơn giản là tôi muốn cung cấp một số cảm hứng. (Tôi hoàn toàn ủng hộ C # và cảm thấy rằng trong nhiều trường hợp C ++ nên áp dụng một số tính năng OOP, vì C # phổ biến chủ yếu do tính dễ sử dụng so với nó).


Cập nhật: Vì C ++ 17 có không gian tên lồng nhau ( nuonsoft.com/blog/2017/08/01/c17-nested-namespaces ), có vẻ như câu trả lời của tôi không còn phù hợp nữa, trừ khi bạn đang sử dụng các phiên bản C ++ cũ hơn .
ワ イ き ん ぐ

1
Tôi yêu Emacs nhiều như vậy, đăng một hình ảnh không phải là lý tưởng. Nó không bao gồm tìm kiếm / lập chỉ mục văn bản và cũng làm cho câu trả lời của bạn khó tiếp cận đối với những khách khiếm thị.
Heinrich hỗ trợ Monica
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.