2010-11-04 39 views
7

Tôi biết rằng bạn thường khởi tạo biến thành viên tĩnh từ bên trong tệp .cpp. Nhưng câu hỏi của tôi là: tại sao bạn lại ?Tại sao bạn _have_ để khởi tạo biến thành viên tĩnh C++?

Dưới đây là một ví dụ:

#include <vector> 

using namespace std; 

class A { 
    public: 
     static vector<int> x; 
}; 

main() { 
    int sz = A::x.size(); 
} 

này đưa ra một lỗi biên dịch: undefined reference to 'A::x'

Tuy nhiên, điều này:

#include <vector> 

using namespace std; 

class A { 
    public: 
     static vector<int> x; 
}; 

// Initialize static member 
vector<int> A::x; 

main() { 
    int sz = A::x.size(); 
} 

biên dịch và chạy tốt.

Tôi có thể hiểu được liệu tôi có đang khởi tạo véc-tơ bằng cách sử dụng thứ gì đó không phải là hàm tạo mặc định, nhưng tôi thì không. Tôi chỉ muốn tạo một vector có kích thước 0. Chắc chắn, bất kỳ thành viên tĩnh sẽ phải được cấp phát bộ nhớ trên khởi tạo chương trình, vậy tại sao trình biên dịch không sử dụng hàm tạo mặc định?

Trả lời

14

Đó là không về khởi, đó là khoảng nét. Hoặc chính xác hơn: đó là về biết được đơn vị biên dịch (cpp) sẽ tổ chức các đối tượng (đã được xác định duy nhất một nơi nào)

Vì vậy, những gì cần thiết đơn giản chỉ để là đặt định nghĩa ở đâu đó, trong một nơi duy nhất, đó là một cpp, để cho trình biên dịch biết rằng khi đối tượng tĩnh của lớp được gọi, nó được định nghĩa ở đó và không nơi nào khác. (nếu bạn cố gắng xác định tĩnh của bạn trong tiêu đề, mỗi cpp bao gồm tiêu đề này sẽ có định nghĩa, không thể biết vị trí cần xác định - và được khởi tạo theo cách thủ công nếu nó được yêu cầu cho bạn sử dụng) .

+2

+1 nhưng bạn nên xóa một trong những con dups. Đối với các đối tượng, RAII làm cho khởi tạo (ngay cả khi chỉ theo constructor mặc định) một hệ quả của định nghĩa. Điều này làm việc cho con trỏ thô, các loại nội trang như 'int'? –

+0

Tôi có nghĩa là bạn có thể thêm khởi tạo ở đó nếu bạn muốn. Tôi sẽ thêm độ chính xác. – Klaim

+0

@Steve POD type constructor là cú pháp duy nhất, vì vậy có nó không hoạt động, nhưng nó không thực sự làm bất cứ điều gì (hoặc thậm chí chính xác hơn, nó được phép làm gì - theo tiêu chuẩn C++). –

2

Định nghĩa khởi tạo cuộc gọi của bạn là gì. Bạn cần xác định thành viên tĩnh ở đâu đó. Phần bên trong lớp chỉ là một tuyên bố. Điều này chủ yếu là do có một định nghĩa bên trong tiêu đề sẽ gây ra vấn đề lớn (vì bạn không thể bao gồm tiêu đề đó vào nhiều hơn một đơn vị dịch mà không gây ra nhiều định nghĩa).

8

Bạn đang xem nó từ điểm của một đơn vị biên dịch đơn.

Nhưng ngôn ngữ phải giả định có thể có nhiều đơn vị biên dịch. Vì vậy, bây giờ trong đó đơn vị biên dịch là đối tượng tĩnh được tạo ra? Về cơ bản trình biên dịch không được phép đưa ra quyết định đó và kỹ sư phải đưa ra quyết định.

3

undefined reference to 'A::x' không phải là lỗi trình biên dịch; đó là lỗi liên kết. Nó có nghĩa là không thể tìm thấy định nghĩa của A::x trong bất kỳ đơn vị dịch nào đang được liên kết với nhau để tạo thành chương trình của bạn. Biến thành viên tĩnh có liên kết bên ngoài và phải được xác định chính xác trong một đơn vị dịch. Bất cứ điều gì với liên kết bên ngoài sẽ không có một định nghĩa được tạo ra bởi trình biên dịch trừ khi bạn viết một.

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