2011-12-01 28 views
7

Trong khi đọc một bài báo, tôi đi qua các cú pháp sau:Làm thế nào một lớp kế thừa từ một mẫu dựa trên chính nó?

template <typename T> 
class MyTemplate 
{ 
    T* member; 
    T* method(); 
    // ... 
} 

class MyClass : public MyTemplate<MyClass> 
{ 
    // ... 
} 

Tôi không hiểu chính xác như thế nào MyClass có thể kế thừa từ một mẫu được dựa trên chính nó. Bạn có thể vui lòng giải thích cách thức hoạt động này?

Trả lời

8

Đây được gọi là Curiously Recurring Template Pattern hoặc CRTP. Nó được sử dụng để đạt được hiệu quả của đa hình tĩnh bằng cách tận dụng thực tế là khi bạn đến MyTemplate<MyClass> trong dòng class MyClass : public MyTemplate<MyClass>, MyClass được định nghĩa bán (đó là loại không đầy đủ) để bạn có thể lưu trữ con trỏ đến loại đó, vv, và làm những việc với nó mà không đòi hỏi một loại hoàn chỉnh.

+0

Tôi sẽ không nói rằng 'MyClass' chưa hoàn thành. Nó có thể là trường hợp mà bạn muốn một số chức năng chung được cung cấp cho lớp này. Ví dụ [Ví dụ] (http://drdobbs.com/cpp/184403484). –

+1

@ R.K tại thời điểm 'công khai MyTemplate ', 'MyClass' thực sự là một loại không đầy đủ. Nó có nghĩa là bạn có thể lưu trữ con trỏ và tài liệu tham khảo, vv –

+0

Có, bạn đã đúng. Bây giờ tôi đã đọc lại mô tả của bạn, nó là chính xác. Tôi nghĩ bạn có nghĩa là MyClass là, ví dụ, một loại không đầy đủ. –

2

Bạn có thể giải thích cách hoạt động của tính năng này không?

Uhm ... nó chỉ .. không? Tiêu chuẩn cụ thể cho phép các tham số mẫu có kiểu không đầy đủ. Và vì không có phương thức nào trong lớp cơ sở CRTP cần một loại được xác định đầy đủ, mọi thứ đều ổn.

§3.9.2 p3 [basic.compound]
Pointers để loại không đầy đủ được phép mặc dù có những hạn chế về những gì có thể được thực hiện với họ (3.11).

§14.3.1 p2 [temp.arg.type]
[Lưu ý: Đối số loại mẫu có thể là loại không đầy đủ (3.9). —end note]

2

Đây được gọi là CRTP. Nó được sử dụng cho tính đa hình tĩnh có thể nhanh hơn sử dụng ảo.

: public MyTemplate<MyClass> 

instantiates MyTemplate<MyClass>, mặc dù kể từ MyClass là không đầy đủ, bạn chỉ có thể sử dụng T theo những cách mà không đòi hỏi một loại hoàn toàn. Chẳng hạn như sử dụng một con trỏ hoặc gọi một hàm thành viên.

Dù sao, chỉ cần nhìn vào đoạn mã của bạn, đó là về cơ bản giống như thế này:

class MyClass 
{ 
    MyClass* member; 
    MyClass* method(); 
} 

Đó là hoàn toàn hợp pháp và dễ hiểu.

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