2011-11-25 31 views
12

Trong C và C++ tất cả các biến tĩnh được khởi tạo theo mặc định thành ZERO.Tại sao tôi nên khởi tạo biến lớp tĩnh trong C++?

Đây không phải là trường hợp của các thành viên dữ liệu lớp tĩnh. Tại sao vậy?

#include <iostream> 
using namespace std; 

int var; 

class MyClass 
{ 
public: 
    static int classVar; 
}; 
int MyClass::classVar = 0; // Why I have to init it here? 

int main(void) 
{ 
    cout << ::var << endl;   // this is initalized to ZERO by default 
    static int var; 
    cout << var << endl;   // and this also is initalized to Zero 
    cout << MyClass::classVar << endl; 

    return 0; 
} 
+0

Bạn không chắc chắn ** var ** được khởi tạo thành 0. Có thể, đôi khi có thể xảy ra, nhưng không chắc chắn. –

+3

@AlessandroPezzato: Trên thực tế, tiêu chuẩn rõ ràng về việc xóa bộ nhớ cho tất cả các biến toàn cầu trước khi thực thi khởi tạo động ... ngoài các giá trị được tạo mà giá trị bằng chữ bị ảnh hưởng, những giá trị mà tôi nghĩ có thể bị ảnh hưởng trực tiếp (theo as-if rule) vì nó không thể kiểm soát được. –

Trả lời

21

Tại phạm vi lớp học,

int MyClass::classVar = 0; // Why I have to init it here? 

là một định nghĩa

static int classVar; 

là một tuyên bố , tức là. lời hứa biến sẽ là được xác định ở đâu đó: bạn phải xác định chính xác một lần các biến mà bạn khai báo.

Lý do là tuyên bố lớp học có thể sẽ được đưa vào nhiều tệp nguồn. Một phần của nó sẽ là một định nghĩa, nó sẽ diễn ra nhân lên: điều này là sai (các ngoại lệ là các hàm inline [member]).

Lưu ý rằng theo nguyên tắc giá trị khởi tạo, bạn có thể nhận cùng với

int MyClass::classVar; // Zero-initialized ! 

như một định nghĩa.

Biến khai báo tại phạm vi không gian tên là định nghĩa quá (trừ khi họ là extern đủ điều kiện):

int var; 

là một tuyên bố, và một định nghĩa: nếu bạn đặt này vào một header và bao gồm nó trong nhiều đơn vị dịch thuật, bạn có một lỗi ("biểu tượng được định nghĩa nhân", hoặc một cái gì đó dọc theo các dòng đó).

[Lưu ý rằng trong C++ (và không có trong C), nếu var trên là const, nó trở nên tự động static và không có vi phạm Rule Một nét nên nó được đưa vào một tiêu đề nhân bao gồm. Điều này đi hơi off topic, nhưng cảm thấy tự do để hỏi chi tiết]

+2

Tôi không chắc đó là những gì đang được hỏi. Tôi đọc đó là "tại sao tôi phải đặt' = 0; 'ở đó?" – Mat

+0

@ Alexandre C .: Sẽ tốt nếu bạn cũng giải thích tại sao điều đó là cần thiết. – Nawaz

+3

Vì vậy, 'int MyClass :: classVar;' đã đủ nếu bạn chỉ cần Zero-initialization? Không bao giờ thử điều đó nhưng theo Std và một câu trả lời đã xóa, nó thực sự làm. – zerm

2

Bạn phải khởi tạo biến dữ liệu lớp tĩnh của mình, bởi vì bạn phải báo cho trình biên dịch biết giá trị của chúng là gì. Các lớp không cần phải có khái niệm về giá trị mặc định.

Loại biến có giá trị "bằng không" hợp lý, cho int là 0, cho double 0,0, cho số string "" vv. Ngược lại, các lớp không nhất thiết phải có giá trị mặc định. Hãy xem xét, ví dụ: class Rectangle. Giá trị bằng không của nó là gì - một hình chữ nhật có không vuông hoặc hình chữ nhật có chiều dài cạnh đơn vị?Đối với biến tĩnh, trình biên dịch yêu cầu bạn định nghĩa chính mình, giá trị biến tĩnh của bạn phải có, bởi vì không phải mọi kiểu dữ liệu đều có thể được khởi tạo bằng giá trị mặc định.

+1

Tôi nghĩ rằng bạn bị nhầm lẫn ở đây: không có gì ngăn cản bạn định nghĩa một biến tĩnh và không khởi tạo biến đó.Nếu biến là một cá thể của một lớp, thì hàm tạo của nó sẽ được gọi là – qdii

+0

Biến tĩnh phải được định nghĩa. Hãy xem xét ví dụ bên dưới ... Nếu "int test :: k;" sẽ được nhận xét thì sẽ không biên dịch. kiểm tra lớp học { công khai: static int k; }; int test :: k; int main() { kiểm tra t; cout << t.k; trả lại 0; } – rakesh

+0

@victor Có, bạn nói đúng, cảm ơn vì đã lưu ý điều đó với tôi. Câu hỏi đặt ra là định nghĩa một biến tĩnh và không phải là khởi tạo của nó. –

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