2012-04-08 52 views
8

Ngược lại với hàm thành viên ảo, tôi cần một giải pháp trong đó một hàm được thực hiện ở mỗi cấp lớp phái sinh có thể được đăng ký để gọi sau đó. Để thực hiện điều này, tôi đã suy nghĩ về việc cung cấp một cơ chế cho các lớp dẫn xuất để đăng ký chức năng của chúng với lớp cơ sở như trong constructor lớp dẫn xuất.Làm thế nào để đăng ký con trỏ hàm thành viên lớp cơ sở với lớp cơ sở

Tôi đang gặp sự cố với đối số con trỏ hàm thành viên. Tôi đã nghĩ rằng Derived có nguồn gốc từ Base, con trỏ this sẽ được tự động đúc.

Điều này có thể được thực hiện gần với những gì tôi đang cố gắng hay tôi cần sử dụng các chức năng thành viên tĩnh, void *static_cast?

class Base 
{ 
protected: 
    typedef void (Base::*PrepFn)(int n); 
    void registerPrepFn(PrepFn fn) {}; 
} 

class Derived : public Base 
{ 
    Derived() { 
     registerPrepFn(&Derived::derivedPrepFn); 
    }; 

    void derivedPrepFn(int n) {}; 

} 

biên dịch báo lỗi:

error: no matching function for call to 'Derived::registerPrepFn(void (Derived::*)(int))' 
note: candidates are:     'void Base::registerPrepFn(void (Base::*)(int))' 
+1

Tôi không chắc chắn chính xác những gì bạn muốn làm. Nhưng chắc chắn là không thể theo cách này; một hàm thành viên được định nghĩa trong 'Derived' không thể được trỏ đến bởi một' Base :: * '. Có lẽ nếu bạn giải thích mục tiêu cấp cao nhất, ai đó có thể đề xuất giải pháp tốt hơn. –

+3

FTR, 'void *' và 'static_cast' sẽ không hoạt động, bởi vì một con trỏ tới hàm thành viên không phải là một con trỏ (có, nó được đặt tên khủng khiếp). –

+0

liên quan đến tĩnh đúc, tôi đã suy nghĩ tôi có thể thực hiện các chức năng thành viên tĩnh và rõ ràng vượt qua xung quanh con trỏ này – NoahR

Trả lời

12

Nếu tất cả bạn cần là đánh bại được thông báo lỗi, sau đó đúc sẽ làm:

class Derived : public Base 
{ 
    Derived() { 
     registerPrepFn(static_cast<PrepFn>(&Derived::derivedPrepFn)); 
    }; 

    void derivedPrepFn(int n) {}; 

} 

Gọi đó là bình thường với một Base* p (miễn là nó thực sự trỏ đến một nguồn gốc): (p->*registered)(0)

Xem http://ideone.com/BB9oy để có ví dụ làm việc.

+0

tốt, tôi không muốn chỉ tắt thông báo lỗi. Điều này có hoạt động không? – NoahR

+0

@NoahR: Có, nó sẽ hoạt động (nhưng hãy cẩn thận với điều kiện in đậm) – jpalecek

+1

Tiêu chuẩn có điều này để nói về chuyển đổi như vậy: "Nếu lớp B chứa thành viên ban đầu, hoặc là lớp cơ sở hoặc lớp dẫn xuất của lớp thành viên ban đầu, con trỏ kết quả đến các điểm thành viên của thành viên ban đầu. Nếu không, kết quả của diễn viên là không xác định. " Tôi sợ rằng một diễn viên như vậy sẽ không làm những gì OP muốn tốt nhất, hoặc không tạo ra một giá trị hữu ích tồi tệ nhất. –

0

này không được phép với oop. Chuyển đổi hành vi được thực hiện bằng cách đa hình hóa lớp của đối tượng tại thời điểm tạo đối tượng.

Nếu bạn cần chuyển đổi hành vi sau khi tạo đối tượng, bạn có thể cấu trúc lại hành vi động thành một nhóm đa hình khác và giữ "con trỏ" cho một thể hiện của một lớp với hành vi đúng. Vui lòng Google mô hình phần mềm "trang trí lớp".

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