2013-02-20 14 views
6

Hôm nay tôi thấy mình tạo ra một mảng tĩnh gồm 2 ints, và vì initalization nội tuyến của nó không được cho phép trong C++ (không phải C++ 11), tôi đã hoàn nguyên sử dụng biến tĩnh của struct type.Cấu trúc tĩnh với các thành viên tĩnh

class MyWidget { 
    ... 
    static const struct Margin { 
    const int horizontal = 1; 
    const int vertical = 1; 
    } margin; 

}; 

Tôi nhận thấy rằng biến nội bộ chỉ được sử dụng một lần cho tất cả các trường hợp của cấu trúc Margin, vì vậy tôi quyết định làm cho chúng tĩnh quá.

class MyWidget { 
    ... 
    static const struct Margin { 
    static const int horizontal = 1; 
    static const int vertical = 1; 
    } margin; 

}; 

Điều kỳ diệu tôi là sự khác biệt giữa khai báo biến cấu trúc tĩnh so với biến cấu trúc tĩnh với thành viên tĩnh. Các đối tượng tĩnh AFAC chỉ được cấp phát một lần trong bộ nhớ, do đó cấu trúc Margin struct chỉ được phân bổ một lần cho dù thành viên của tôi có tĩnh hay không.

Tôi có bỏ lỡ điều gì đó không? Liệu có tồn tại một sự khác biệt hay chỉ là một đường cú pháp?

+8

Không có thứ gì như "cấu trúc tĩnh" trong C++, tĩnh là bộ lưu trữ lớp lưu trữ và áp dụng cho các biến hoặc hàm, không phải kiểu. – PlasmaHH

+0

Bạn không nên quay trở lại sử dụng cấu trúc với các thành viên được đặt tên thay vì một mảng các phần tử chưa được đặt tên .. nó phải là cách khác xung quanh .. –

+0

Tôi đã googled một chút và dường như tôi không thể tìm thấy kết quả có ý nghĩa "cấu trúc tĩnh". Bạn có lẽ đến từ thế giới C#? – antonijn

Trả lời

8

Bạn có vẻ hơi bối rối về "cấu trúc tĩnh", vì trong C++, không có những thứ như cấu trúc tĩnh (trái ngược với các ngôn ngữ như C#, nơi các lớp tĩnh là giải pháp cho thực tế là không có chức năng toàn cục).

Những gì bạn đang làm, đang tạo một phiên bản của lớp đó và tạo dụ (margin) tĩnh (và không đổi). Vì vậy, cấu trúc của bạn không phải là tĩnh, bạn chỉ đơn giản là xác định một cấu trúc, và làm cho một ví dụ static const của nó, thuộc về MyWidget. Sự khác biệt giữa hai ví dụ cụ thể hiện nay, nên khá rõ ràng.

Trong ví dụ đầu tiên, bạn đang tạo ra một biến tĩnh được gọi là lề, thuộc MyWidget, có nghĩa là bạn có thể truy cập vào horizontal thành viên như vậy

MyWidget::margin.horizontal 

đâu margin là trường hợp bạn đã tạo.

Trong khi nếu bạn đã làm cho các thành viên của cấu trúc tĩnh, bạn sẽ không thể làm điều đó. Thay vào đó, bạn sẽ phải truy cập chúng như vậy:

MyWidget::Margin::horizontal 

đâu Marginstruct. Tuy nhiên, lưu ý rằng trong trường hợp thứ hai, không cần đối với cá thể tĩnh margin, vì nó không có trường cá thể nào được liên kết với nó.

+0

vì vậy trong trường hợp thứ hai tôi có thể thả 'const tĩnh struct Margin {...} margin;' và chỉ đơn giản là 'const struct Margin {...} margin;'? –

+0

@PavloDyban Sau đó, 'margin' sẽ là một biến mẫu, có nghĩa là bạn cần một cá thể' MyWidget' để nó có thể hoạt động. – antonijn

3

Có, có sự khác biệt đáng kể. Trong cả hai trường hợp, bạn khai báo MyWidget::margin là loại MyWidget::Margin và chúng là tĩnh. Trong trường hợp đầu tiên, margin là một đối tượng có hai trường, horizontalvertical. Trong trường hợp thứ hai, margin là một đối tượng không có trường và bạn có thể chỉ cần thả đối tượng đó.

Trong trường hợp đầu tiên mà bạn cần phải sử dụng hình thức margin.vertical (hoặc MyWidget::margin.vertical nếu truy cập từ bên ngoài MyWidget) để truy cập vào các lĩnh vực, trong trường hợp thứ hai, bạn có thể làm điều đó như Margin::vertical (hoặc MyWidget::Margin::vertical) này.

+0

tại sao 'margin' trong trường hợp thứ hai là đối tượng không có trường? không phải là biến tĩnh bằng cách nào đó liên kết với cấu trúc? 'struct Margin' phải biết nơi để lấy giá trị của ngang và dọc khi tôi gọi' Margin :: vertical', phải không? –

+2

Trường tĩnh không phải là một phần của đối tượng. Bạn có thể nghĩ về các trường tĩnh của Margin như thể chúng là các biến toàn cầu trong một không gian tên. – lego

+0

Đây là nó! Tôi đã nhận nó ngay bây giờ. Bởi vì các biến tĩnh là như nhau trên tất cả các trường hợp, tôi cứ suy nghĩ về con trỏ thay thế các biến này, nhưng tôi đã quên về các vars toàn cầu. Cám ơn! –

4

Có thực sự là một sự khác biệt:

class MyWidget { 
    ... 
    static const struct Margin { 
    const int horizontal = 1; 
    const int vertical = 1; 
    } margin; 


    void foo() { 
    Margin anotherMargin = { 3, 4 }; 
    } 
}; 

Điều này tạo ra một thể hiện của Margin, có các thành viên khác nhau. static trong static const struct Margin {...} margin; áp dụng cho biến số margin, không áp dụng cho lớp/cấu trúc Margin. Điều đó có nghĩa là chỉ có một đối tượng Margin được chia sẻ bởi tất cả các đối tượng MyWidget, nhưng bạn có thể tạo ra các đối tượng Margin khác có các giá trị khác nhau. Đoạn mã trên sẽ không biên dịch với horizontalvertical là tĩnh, bởi vì sau đó đối tượng Margin sẽ không có biến thành viên (thống kê không phải là thành viên thực) và do đó tất cả đối tượng Lề sẽ chia sẻ giá trị horizontalvertical.