2011-12-15 29 views
18

Trong CRTP pattern, chúng tôi gặp sự cố nếu chúng tôi muốn giữ chức năng triển khai trong lớp dẫn xuất như được bảo vệ. Chúng ta phải khai báo lớp cơ sở như một người bạn của lớp dẫn xuất hoặc sử dụng something like this (Tôi chưa thử phương thức này trên bài viết được liên kết). Có cách nào khác (đơn giản) cho phép giữ chức năng triển khai trong lớp dẫn xuất như được bảo vệ không?CRTP với thành viên có nguồn gốc được bảo vệ

Edit: Đây là một ví dụ mã đơn giản:

template<class D> 
class C { 
public: 
    void base_foo() 
    { 
     static_cast<D*>(this)->foo(); 
    } 
}; 


class D: public C<D> { 
protected: //ERROR! 
    void foo() { 
    } 
}; 

int main() { 
    D d; 
    d.base_foo(); 
    return 0; 
} 

Đoạn mã trên cho error: ‘void D::foo()’ is protected với g ++ 4.5.1 nhưng biên dịch nếu protected được thay thế bằng public.

+0

Đó không phải là những gì các chức năng ảo là gì? –

+2

@BoPersson, các hàm ảo dành cho đa hình thời gian chạy, CRTP dành cho tính đa hình thời gian biên dịch. Có cả phòng trên thế giới cho cả hai. Xem http://en.wikipedia.org/wiki/Curiously_recurring_template_pattern –

+0

@Mark - Có chắc chắn, nhưng nếu yêu cầu là để gọi một chức năng được bảo vệ trong một lớp dẫn xuất, ảo trông giống như một sự phù hợp. :-) –

Trả lời

21

Đó không phải là vấn đề gì cả và được giải quyết với một dòng trong lớp có nguồn gốc:

friend class Base<Derived>;

#include <iostream> 

template< typename PDerived > 
class TBase 
{ 
public: 
    void Foo(void) 
    { 
    static_cast< PDerived* > (this)->Bar(); 
    } 
}; 

class TDerived : public TBase<TDerived> 
{ 
    friend class TBase<TDerived> ; 
protected: 
    void Bar(void) 
    { 
    std::cout << "in Bar" << std::endl; 
    } 
}; 

int main(void) 
{ 
TDerived lD; 

lD.Foo(); 

return (0); 
} 
Các vấn đề liên quan