2010-07-07 59 views
25

Tôi nhầm lẫn phải làm gì khi có không gian tên lồng nhau và khai báo đối tượng.Không gian tên lồng nhau trong C++

Tôi đang chuyển một số mã liên kết với một thư viện tĩnh có một vài không gian tên.

Ví dụ về những gì tôi đang nói về:

namespace ABC { 

    namespace XYZ { 

     //STUFF 
    } 
} 

Trong mã tôi phải làm gì để khai báo một đối tượng mà là trong namespace XYZ?

nếu tôi cố gắng:

XYZ::ClassA myobject; 

hay:

ABC::XYZ::ClassA myobject; 

hay:

ABC::ClassA myobject; 

tôi nhận được

không tên một loại

lỗi, mặc dù chắc chắn tồn tại ClassA.

Điều gì là phù hợp ở đây?

+3

Tôi muốn nói - không sử dụng không gian tên lồng nhau, giữ cho lược đồ không gian tên của bạn càng đơn giản càng tốt. –

+1

Những gì bạn đã thử rõ ràng là chính xác. Có lẽ bạn đã nhập sai một không gian tên/lớp trong mã thực của bạn? Bạn cũng có thể kiểm tra trường hợp ** ký tự ** (đây là lỗi thường gặp). – ereOn

+1

Chỉ cần đảm bảo ... Bạn biết khai báo một lớp mới trong không gian tên lồng nhau khác với tham chiếu một đối tượng được khai báo trong một thư viện bên ngoài từ bên trong chúng. – Jay

Trả lời

40

Nó phụ thuộc vào không gian tên bạn đã là:

Nếu bạn đang ở trong không gian tên này hay cách khác, không gian tên không liên quan, sau đó bạn phải xác định cho toàn bộ con đường ABC::XYZ::ClassA.

Nếu bạn đang ở ABC bạn có thể bỏ qua ABC và chỉ viết XYZ::ClassA.

Ngoài ra, đáng nói rằng nếu bạn muốn đề cập đến một chức năng mà không có trong một không gian tên (hoặc "root" không gian tên), bạn có thể thêm tiền tố nó bằng cách :::

Ví dụ:

int foo() { return 1; } 

namespace ABC 
{ 
    double foo() { return 2.0; } 

    void bar() 
    { 
    foo(); //calls the double version 
    ::foo(); //calls the int version 
    } 
} 
4

Nếu myobject được khai báo trong không gian tên đó và bạn muốn khai báo lại (để xác định nó), bạn làm điều đó bằng cách đặt trước tên của nó, không phải kiểu của nó.

ClassA ABC::XYZ::myobject; 

Nếu loại của nó được khai báo trong namespace đó quá, bạn cũng cần phải thêm tiền tố tên của các loại

ABC::XYZ::ClassA ABC::XYZ::myobject; 

Nó hiếm khi cần thiết để redeclare một đối tượng như thế. Thông thường khai báo đầu tiên của một đối tượng cũng là định nghĩa của nó. Nếu bạn muốn khai báo đối tượng đầu tiên, bạn phải thực hiện nó trong không gian tên đó. Tuyên bố sau đây và xác định "myobject"

namespace ABC { 
    namespace XYZ { 
    ClassA myobject; 
    } 
} 

Nếu bạn đã xác định trong đối tượng như thế này, bạn tham khảo bằng cách nói ABC::XYZ.Bạn không phải "khai báo" đối tượng đó bằng cách nào đó để sử dụng nó tại địa phương

void f() { 
    ABC::XYZ::myobject = someValue; 

    // you *can* however use a using-declaration 
    using ABC::XYZ::myobject; 
    myobject = someValue; 
} 
+0

"Thường thì tuyên bố đầu tiên của một đối tượng cũng là định nghĩa của nó" Điều này có vẻ sai. Nếu bạn muốn khai báo một số đối tượng trong một tệp tiêu đề, nó không được định nghĩa ở đó. Nếu không, nếu có 2 tệp cpp bao gồm tiêu đề này và chúng tôi sẽ biên dịch và thử liên kết các tệp cpp này, trình liên kết sẽ trả về lỗi về định nghĩa trùng lặp. Nếu đoạn mã thứ hai sắp có trong một tiêu đề, nó sẽ là 'namespace ABC {namespace XYZ {extern ClassA myobject;}}' và sau đó trong một tệp cpp tương ứng nên có 'ClassA ABC :: XYZ :: myobject; '(nếu ClassA không nằm trong không gian tên) – Number47

+0

@ Number47 tại sao nó sai? Tôi không nói "Tất cả các tuyên bố của các đối tượng là định nghĩa", mà bạn dường như giả định tôi có. –

+0

@Johnnes Tôi không nói rằng "Trong mọi trường hợp nó sai". Nhưng nghiêm túc. Nếu chúng ta đang nói về những thứ như 'namespace ABC {...}', thì rất có khả năng chúng ta là về các tệp tiêu đề (tôi có sai không?). Nhưng nó là một thực tế xấu để đặt một cái gì đó như 'ClassA myobject;' trong một tiêu đề vì nó có thể gây ra lỗi liên kết, như tôi đã chỉ ra. Vì vậy, trong đoạn 3'rd - Tôi xin lỗi, trong bài trước nó cũng phải là 3'rd - nên có 'extern ClassA myobject;' hoặc có một lưu ý rằng đoạn mã này sắp được sử dụng trong các tệp cpp, không có trong tiêu đề. Nói cách khác chúng ta có thể hiểu lầm người đọc của mình. :) – Number47

Các vấn đề liên quan