2011-08-31 26 views
9

mã này biên dịch và chạy không có lỗi:Tại sao tôi có thể gọi hàm tạo riêng từ phạm vi toàn cục?

class foo{ 
    static foo *ref; 
    foo(){} 
    public: 
    static foo *getRef(){ 
     return ref; 
    } 
    void bar(){} 
}; 

foo* foo::ref = new foo; // the construcrtor is private! 

int main(int argc, const char *argv[]) 
{ 
    foo* f = foo::getRef(); 
    f->bar(); 
    return 0; 
} 

ai đó có thể giải thích lý do tại sao các nhà xây dựng có thể được gọi là?

Trả lời

15

Phạm vi đó không phải là toàn cục - các thành viên tĩnh nằm trong phạm vi lớp và do đó biểu thức khởi tạo của chúng cũng ở phạm vi lớp.

+4

Thật vậy, thay thế biểu thức bằng 'foo * ref = new foo;' (lưu ý không có 'foo ::') để có lỗi trình biên dịch! –

10

Câu trả lời là câu trả lời không có sẵn trong phạm vi toàn cầu. Trình khởi tạo của một thành viên tĩnh được định nghĩa là bên trong phạm vi lớp, vì vậy nó có quyền truy cập vào các thành viên riêng tư.

§9.4.2/2 [...] Biểu thức khởi tạo trong định nghĩa của thành viên dữ liệu tĩnh nằm trong phạm vi của lớp (3.3.6).

-2

Hình thức khởi tạo thành viên tĩnh này không cần thiết trong phiên bản cũ hơn C++. Chúng được tạo ra trong các phiên bản sau của C++.

Và, hình thức khởi tạo thành viên tĩnh này thường sẽ được sử dụng để khởi tạo các thành viên tĩnh trước khi tạo bất kỳ đối tượng lớp nào.

(E.g) int MyClass::objectsCounter=0; 

Nhưng,

foo* foo::ref = new foo; 

tuyên bố này bạn chỉ là khởi tạo một thành viên tĩnh (đó là kiểu con trỏ) bằng cách tạo ra một đối tượng mới.

Và trong trường hợp này, bạn đang intializing một thành viên tư nhân bằng cách gọi một phương pháp riêng của lớp riêng của mình.

Do đó không có vai trò của phạm vi toàn cầu tại đây.

+0

-1 Bạn đang đề cập đến gì về các bản phát hành "cũ hơn" và "sau này" * của C++? AFAIK, đây là một phần của thiết kế ngôn ngữ kể từ tiêu chuẩn đầu tiên vào năm 1998. Hơn nữa, việc sử dụng 'foo' mới luôn tạo ra một đối tượng. Câu lệnh thực hiện 2 điều: a) một thể hiện kiểu 'foo' được tạo; và b) 'foo :: ref' được gán một con trỏ tới đối tượng mới được cấp phát. –

+0

@ André Caron Cảm ơn ý kiến ​​của bạn. Tôi đã chỉnh sửa bài đăng của mình. Tôi thực sự muốn nói thông tin này chỉ. Nhưng tôi đã cung cấp sai thông tin. Về cũ và sau C++: -, thông tin được cung cấp bây giờ được thực hiện dưới dạng COMPLETE REFERENCE-HERBERT. –

+0

Nếu bạn có kế hoạch lập trình C++ chuyên nghiệp, bạn nên cân nhắc sử dụng [C++ sách được cộng đồng C++ đề xuất] (http://stackoverflow.com/questions/388242/the-definitive-c-book-guide-and-list). –

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