2010-01-21 24 views
8

Tôi cần ngăn không cho lớp bắt nguồn từ vì vậy tôi tự nghĩ, đây là thứ mà Boost chắc chắn đã làm. Tôi biết họ có một noncopyable, họ phải có một nonderivable ...Có cách nào, sử dụng các mẫu, để ngăn không cho lớp học có thể phát sinh trong C++

Hãy tưởng tượng sự ngạc nhiên của tôi khi tôi không thể tìm thấy nó ....

Đó tôi đã suy nghĩ .. Có phải là một lý do. Có thể không thể sử dụng các mẫu ..

Tôi chắc chắn nếu nó dễ dàng, nó nằm trong thư viện tăng cường.

tôi biết làm thế nào để làm điều đó mà không sử dụng các mẫu, tức là sử dụng một lớp cơ sở với một constructor tin tức

class ThatCantBeDerived; // Forward reference 

class _NonDeriv 
{ 
    _NonDeriv() {} 
    friend class ThatCantBeDerived; 
}; 

class ThatCantBeDerived : virtual public _NonDeriv 
{ 
public: 
    ThatCantBeDerived() : 
     _NonDeriv() 
    { 
    } 
}; 

Hoặc một cái gì đó như thế này ..

Có thể đó là tài liệu tham khảo về phía trước gây ra vấn đề , hoặc có thể không có một cách cầm tay để đạt được nó ..

Dù bằng cách nào, tôi không chắc chắn lý do tại sao nó không phải là trong thúc đẩy ..

Bất kỳ ý tưởng?

+0

ScaryA, ra khỏi curiocity nhàn rỗi, có thể bạn vui lòng tiết lộ lý do tại sao một muốn có một lớp học không thể sinh tồn? (Câu hỏi trung thực - Tôi chưa bao giờ có một thiết kế mà có thể đã kêu gọi như vậy, nhưng tôi cho rằng câu hỏi của bạn có một số nguồn thực tế). – DVK

+0

Số nhận dạng bắt đầu bằng dấu gạch dưới theo sau là chữ cái viết hoa (dưới dạng số nhận dạng bắt đầu bằng dấu gạch dưới kép) được dành riêng cho việc triển khai (trình biên dịch + thư viện). Bạn không nên gọi mẫu của bạn '_NonDeriv'. –

+0

@DVK Giả sử bạn đang thiết kế một công cụ đang sử dụng cấu trúc cố định mà lớp ánh xạ trực tiếp (tức là cấu trúc sk_buff) và tất cả thư viện của bạn làm cho việc tối ưu hóa/giả định về ánh xạ đó. Bạn chắc chắn không muốn ai đó có thể thay đổi bạn? – ezpz

Trả lời

2

Theo spec hiện nay, nó được một cách rõ ràng cấm "người bạn" một cuộc tranh luận mẫu, vì vậy templatizing ví dụ của bạn sẽ làm cho nó không tiêu chuẩn phù hợp. Tăng có lẽ sẽ không muốn thêm một cái gì đó như thế vào thư viện của nó. Tôi tin rằng hạn chế này đang được thư giãn trong Ox tuy nhiên, và có cách giải quyết cho trình biên dịch.

+0

Để công bằng, thuế vptr được đề cập trong C++ faq lite có lẽ cũng là một lý do rất tốt –

3

Không có cách nào trong C++ ngăn chặn nguồn gốc - bạn không thể ngăn chặn tình trạng này:

class A {}; 

class B : public A {}; 

Tuy nhiên, có một số cách ngăn ngừa instantiation của đối tượng thuộc loại B. Cho dù đây là giá trị những rắc rối có thể gây tranh cãi. Tôi muốn ghi lại rằng lớp A không nhằm mục đích dẫn xuất, và cho nó một destructor không ảo.

Ngoài ra, lưu ý rằng tên _NonDeriv được đặt trước trong C++ để triển khai, cũng như tất cả các tên bắt đầu bằng dấu gạch dưới và chữ hoa. Bạn không được phép tạo các tên như vậy trong mã của riêng bạn.

0

lẽ biến ví dụ của bạn thành một mẫu, sử dụng CRTP - mẫu hoa văn một cách tò mò lặp đi lặp lại:

template <typename T> 
_NonDeriv 
{ 
    _NonDeriv() {} 
    friend class T; 
}; 

class ThatCantBeDerived : virtual public _NonDeriv<ThatCantBeDerived> 
{ 
public: 
    ThatCantBeDerived() : 
     _NonDeriv() 
    { 
    } 
}; 

Có thể làm việc ...

+0

Ah, câu trả lời của Todd Gardner cho thấy điều này sẽ không hoạt động (cho đến khi C++ 0x có thể). Rất tốt. – tony

+0

Đó là khá nhiều chính xác những gì tôi đã làm.Lý do duy nhất tôi dừng lại là khi tôi nghĩ rằng điều này phải được thực hiện đã tăng ... Cho đến khi tôi tìm thấy nó không phải là ... – ScaryAardvark

+0

Và sau đó @Todd Gardner vui lòng giải thích lý do tại sao :) – ScaryAardvark

1

Adobe có một giải pháp không hoàn hảo cho việc này sử dụng các mẫu.

Vấn đề là do mẫu không thể khai báo bạn bè phụ thuộc vào đối số [*] nó dựa trên hàm tạo đang được bảo vệ thay vì riêng tư. Nó là một giải pháp một phần trong đó nó sẽ kích hoạt một lỗi trình biên dịch khi ai đó nhầm lẫn quyết định lấy được từ lớp của bạn, nhưng nó không phải là một giải pháp hoàn chỉnh vì ai đó cố tình có thể ép buộc thừa kế.

template <typename SealedClass> 
class seal 
{ 
protected: 
    seal() {} 
}; 

class Sealed : private virtual seal<Sealed> 
{ 
//... 
}; 

class NaiveExtension : public Sealed { // fails 
    NaiveExtension() {} // NaiveExtension cannot call seal<Sealed> constructor 
}; 

class BreakingExtension : public Sealed, private virtual seal<Sealed> { 
    BreakingExtension() : seal<Sealed>(), Sealed() {} // now it can 
}; 

Lợi thế là nó có thể được templated (thư viện adobe thực sự xác định macro sẽ ẩn 'ảo riêng tư' từ trình đọc thông thường). Điểm bất lợi là nó có thể bị hỏng.

Sau đó, một lần nữa, bạn luôn có thể làm những gì C++ Hỏi đáp gợi ý cho một số câu hỏi về chặn một số chức năng:

'how can I inhibit people from...': write a comment not to do it

'but how do I really inhibit others from...': write a comment: You will be fired if...

'but how do I actually block it in case they don't follow the comment?': fire them

[*] Hạn chế này sẽ được lấy đi với tiêu chuẩn sắp tới, bất cứ khi nào có sẵn, bất cứ khi nào thực hiện trong trình biên dịch ...

1

dễ dàng:

làm cho tất cả các nhà thầu tư nhân:
Sau đó nobdy thể derivce từ bạn. Tất nhiên điều này cho biết thêm vấn đề Othe như bạn không thể instanciate một biến của đối tượng, nhưng có cách giải quyết cho rằng việc sử dụng các phương pháp thành viên public static và bạn bè:

#include <memory> 
class InstnaceCantDeriveFromMe; 
class CantDeriveFromMe 
{ 
    private: 
     friend class InstnaceCantDeriveFromMe; 
     CantDeriveFromMe() 
     {} 

    public: 
     static std::auto_ptr<CantDeriveFromMe> getDynamicObj() 
     { 
      return std::auto_ptr<CantDeriveFromMe>(new CantDeriveFromMe()); 
     } 
}; 

class Plop: public CantDeriveFromMe 
{ 
}; 

class InstnaceCantDeriveFromMe 
{ 
    private: 
     CantDeriveFromMe instnace; 
    public: 
     CantDeriveFromMe& get() {return instnace;} 
}; 

int main() 
{ 
    std::auto_ptr<CantDeriveFromMe> a =  CantDeriveFromMe::getDynamicObj(); 
    InstnaceCantDeriveFromMe   b; 


    // This fails to compile: 
    Plop        c; 
} 
Các vấn đề liên quan