2011-08-17 27 views
18

Tôi vừa viết một lớp với một số thành viên dữ liệu tĩnh, nhưng bây giờ tôi nhận được lỗi về "tài liệu tham khảo không xác định". Tại sao nó không hoạt động? Tôi đang làm gì sai?Có nghĩa là gì khi có một tham chiếu không xác định cho một thành viên tĩnh?

(Lưu ý:.. Đây được hiểu là một mục để Stack Overflow's C++ FAQ Nếu bạn muốn phê bình ý tưởng cung cấp một câu hỏi thường gặp ở dạng này, sau đó the posting on meta that started all this sẽ là nơi để làm điều đó câu trả lời cho câu hỏi đó là giám sát trong C++ chatroom, nơi FAQ ý tưởng bắt đầu ra ở nơi đầu tiên, vì vậy câu trả lời của bạn rất có khả năng để có được đọc bởi những người đã đưa ra ý tưởng.)

+0

http://www.parashift.com/c++-faq-lite/ctors.html#faq-10.12 – PlasmaHH

Trả lời

26

Để hiểu điều này, bạn nên có một hiểu biết tốt về compiling and linking, và sự khác biệt giữa declarations and definitions.


Hãy xem xét các lớp sau đây:

//In header file 
class Example { 
    static bool exampleStaticMember; 
}; 

Ở đây, exampleStaticMember được khai báo nhưng không được định nghĩa. Điều này có nghĩa rằng nếu exampleStaticMember được sử dụng theo cách có nghĩa là nó phải có địa chỉ thì phải có định nghĩa riêng cho nó. Nói chung, không có tuyên bố của một thành viên dữ liệu tĩnh trong định nghĩa lớp là định nghĩa của thành viên đó.

Khai báo bắt buộc thường được đặt trong tệp cpp chứa các định nghĩa khác cho các thành viên của lớp. Nó phải ở trong cùng một không gian tên như định nghĩa lớp. Định nghĩa thường trông giống như:

//In source file: 
//This may optionally have an initialiser (eg "= true") 
bool Example::exampleStaticMember; 

định nghĩa có thể được đặt ở bất kỳ tập tin cpp, nhưng nó không nên được đặt trong tiêu đề với lớp, bởi vì điều đó sẽ có khả năng phá vỡ các One Definition Rule.

Là một trường hợp đặc biệt, nếu biến thành viên tĩnh là một const không thể thiếu hoặc liệt kê loại sau đó nó có thể có một initialiser trong định nghĩa lớp:

//In header file 
class Example { 
    static const int initialised = 15; 
}; 

Trong trường hợp này, định nghĩa trong file cpp là vẫn được yêu cầu nhưng không được phép có người khởi tạo:

//In source file 
//Note: no initialiser! 
const int Example::initialised; 

Thành viên tĩnh đã được khởi tạo như thế này có thể được sử dụng trong biểu thức không đổi.

Templates

Đối với một thành viên dữ liệu tĩnh của một mẫu, điều hơi khác nhau. Thành viên tĩnh phải được xác định trong tiêu đề cùng với phần còn lại của lớp:

//In header file 
template<typename T> 
class Example { 
    static int exampleInt; 
    static T exampleT; 
} 
template<typename T> int Example<T>::exampleInt; 
template<typename T> T Example<T>::exampleT; 

Điều này hoạt động vì có ngoại lệ cụ thể cho Quy tắc một định nghĩa cho thành phần dữ liệu tĩnh của mẫu lớp.

Các ứng dụng khác của tĩnh

Khi từ khóa static được áp dụng cho các chức năng và các đối tượng mà không phải là trong một phạm vi lớp học có thể mất trên một ý nghĩa rất khác nhau.

Khi áp dụng cho các đối tượng trong phạm vi chức năng, nó khai báo đối tượng được khởi tạo trong lần thực thi đầu tiên của hàm và sau đó giữ giá trị của nó giữa các cuộc gọi hàm.

Khi áp dụng cho các đối tượng hoặc hàm tại phạm vi không gian tên (bên ngoài bất kỳ định nghĩa lớp hoặc chức năng nào), nó khai báo đối tượng hoặc hàm với internal linkage. Việc sử dụng này không được chấp nhận cho các đối tượng vì số unnamed-namespace cung cấp giải pháp thay thế tốt hơn.

+0

"Là trường hợp đặc biệt, nếu biến thành viên tĩnh là loại tách rời hoặc kiểu liệt kê thì có thể có initialiser trong định nghĩa lớp "#:. Bạn có nghĩa là tuyên bố lớp * ở đây không? –

+0

@SamGoldberg: Không - nếu tôi đã nói _declaration_, thì tôi sẽ đề cập đến một tuyên bố chuyển tiếp (ví dụ: 'class Example;'). Bởi _definition_, tôi có nghĩa là mã tuyên bố các thành viên của lớp. (Có, những thành viên này có thể được định nghĩa bên ngoài định nghĩa lớp học, nhưng điều đó không quan trọng ở đây). – Mankarse

5

bạn phải nhanh chóng thành viên tĩnh được định nghĩa trong một tiêu đề trong tệp .cpp. Ví dụ:

// foo.h 

class foo { 
    static int X; 
}; 


// foo.cpp 

#include "foo.h" 

int foo::X = 0; 
Các vấn đề liên quan