2009-06-29 33 views

Trả lời

73

Khi một lớp (được dự định là) một lớp trừu tượng, một hàm tạo được bảo vệ là chính xác. Trong tình huống đó, bạn không muốn các đối tượng được khởi tạo từ lớp nhưng chỉ sử dụng nó để kế thừa từ đó.

Có các trường hợp sử dụng khác, như khi một tập hợp các thông số xây dựng nhất định nên được giới hạn trong các lớp dẫn xuất.

+7

+1 Nhưng không nhất thiết phải là một lớp trừu tượng. Nó thường là trường hợp mặc dù. – ralphtheninja

+4

Không đủ để khai báo một hàm thuần ảo để xác định một lớp cơ sở? Hoặc ở trên là không có chức năng ảo thuần túy. Sự kiện sáng tạo cho lớp Bắt nguồn của lớp Tóm tắt như vậy là gì? –

+0

@Henk Holterman Chắc chắn không - xem Phần 10.4 của Tiêu chuẩn C++, có tên là "Lớp trừu tượng" –

11

một sử dụng có thể là mô hình nhà máy

6

Một constructor bảo vệ có nghĩa là thành viên duy nhất có nguồn gốc có thể xây dựng các thể hiện của lớp (và các trường hợp có nguồn gốc) sử dụng constructor đó. Điều này nghe có vẻ hơi gà và trứng, nhưng đôi khi hữu ích khi thực hiện các nhà máy lớp học.

+3

Về mặt kỹ thuật, điều này chỉ áp dụng nếu TẤT CẢ các ctors được bảo vệ. – MSalters

+1

lớp bạn bè cũng có thể gọi hàm tạo được bảo vệ (không chỉ các lớp dẫn xuất). –

+0

...và việc sử dụng một lớp người bạn gọi là constructor được bảo vệ sẽ là trường hợp đối tượng có các thành viên không đổi (được thiết lập bởi hàm tạo) nhưng cần phải được công khai, nhưng không bao giờ được đặt bởi bất kỳ truy cập công cộng nào khác, đảm bảo rằng đối tượng sẽ không được tạo ở đâu đó và dữ liệu do đó sẽ không bị sửa đổi ở bất kỳ nơi nào khác. – osirisgothra

3

Để cho một lớp con sử dụng một hàm tạo nên không thể truy cập trực tiếp vào trình tạo nhanh.

3

Bạn có thể sử dụng nó để hạn chế các lớp học mà có thể tạo ra nó, ví dụ:

class Level 
{ 
private: 

Level(); 
¨Level(); 

friend class LevelManager; 
}; 

Lớp duy nhất có thể tạo ra một thể hiện của nó là lớp LevelManager, vì vậy bạn sẽ luôn luôn biết rằng Cấp instance được tạo trong LevelManager.

+0

Trong khi đúng, đó là một hàm tạo riêng, không được bảo vệ. – David

+0

ahaha xin lỗi, tôi đã đọc sai. Tôi có nên xóa bài viết của mình không? –

7

Nhà thầu ngoài công lập rất hữu ích khi có các yêu cầu xây dựng không thể được đảm bảo duy nhất bởi nhà xây dựng. Ví dụ, nếu một phương thức khởi tạo cần phải được gọi ngay sau hàm tạo, hoặc nếu đối tượng cần đăng ký chính nó với một đối tượng container/manager nào đó, thì điều này phải được thực hiện bên ngoài hàm tạo. Bằng cách hạn chế quyền truy cập vào hàm tạo và chỉ cung cấp một phương thức factory, bạn có thể đảm bảo rằng bất kỳ cá thể nào mà người dùng nhận sẽ thực hiện tất cả các bảo đảm của nó. Điều này cũng thường được sử dụng để thực hiện một Singleton, mà thực sự chỉ là một đảm bảo lớp làm cho (rằng sẽ chỉ có một trường hợp duy nhất).

Lý do làm cho hàm tạo được bảo vệ, chứ không phải là riêng tư, cũng giống như để thực hiện bất kỳ phương thức hoặc trường nào khác được bảo vệ thay vì riêng tư: để có thể được thừa hưởng bởi trẻ em. Có lẽ bạn muốn có một phương thức công cộng, không ảo trong lớp cơ sở, nó trả về các tham chiếu đến các cá thể của các lớp dẫn xuất; các lớp dẫn xuất rõ ràng muốn truy cập vào các hàm tạo cha mẹ, nhưng bạn vẫn không muốn tạo chúng bên ngoài nhà máy của bạn.

2

Đối với phương pháp nhà máy có tác dụng phụ.

class mine { 

    private: 
    mine() {}; 

    protected: 
    mine(int id) : m_id(id) {}; 

    int m_id; 
    static int m_count; 

    public: 
    static mine* CreateOneOfMe() { 
     return mine(m_count++); 
    } 

    int GetId() { return m_id; } 

}; 

Điều này tạo ra trường hợp của lớp và đảm bảo rằng mỗi lớp có một số nguyên tăng dần duy nhất. Lưu ý rằng nếu hàm tạo bạn muốn sử dụng không phải là mặc định, bạn cũng phải ẩn mặc định.

5

Một hàm tạo được bảo vệ có thể được sử dụng để tạo lớp trừu tượng một cách hiệu quả khi không có phương thức nào là thuần ảo.

Nó không hoàn toàn trừu tượng theo nghĩa C++ vì lớp bạn bè vẫn có thể sử dụng nó mà không ghi đè, nhưng sau đó bạn sẽ phải khai báo chúng.

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