2012-01-09 44 views
5

Tôi có một lớp cơ sở và các lớp học xuất phát từ nó. Lớp cơ sở Controllable hoạt động như một giao diện cho vòng lặp đầu vào và các lớp khác xuất phát từ nó để có được vị trí trong vòng lặp đó để nhận các sự kiện như khi nhấn một phím.C++: Các chức năng ảo cần gọi cùng một mã?

class Controllable{ 
public: 
    virtual void setActive(bool state) { m_active = state; } 
    virtual void input(Event & e) =0; 
private: 
    bool m_active; 
}; 

class Button : public Controllable{ 
public: 
    void setActive(bool state){ /*do extra work*/ m_active = state; } 
    void input(Event & e) override; 
}; 

Kể từ khi giao dịch Button lớp với các sự kiện từ một hàng đợi sự kiện, đặt nó vào hoạt động (trong đó có nó ra khỏi vòng lặp đầu vào) có thể gây ra nó để bỏ lỡ sự kiện quan trọng như một chìa khóa là unpressed, vì vậy nó cần thêm để đưa nó vào trạng thái không hoạt động thân thiện nếu nó trở nên hoạt động trở lại sau.

Câu hỏi của tôi, những gì là cách tốt nhất để đảm bảo rằng setActive luôn có tác dụng dự định chuyển đổi m_active sang trạng thái đúng, trong khi cùng một lúc, không đòi hỏi các lớp thừa kế để xác định nó, trừ khi họ cần phải đính kèm thêm cần mã?

+0

Bạn có ';' sau '} 'chức năng, xem cho họ. –

+0

Mr.TAMER - đã được sửa! Tôi có một chút ngứa ngáy; ngón tay –

Trả lời

9

Giữ setActive phương pháp không ảo và sau đó xác định một riêng biệt protected phương pháp activeChanged rằng lớp trẻ có thể ghi đè lên

class Controllable{ 
public: 
    void setActive(bool state) { m_active = state; activeChanged(state); } 
    virtual void input(Event & e) = 0; 
protected: 
    virtual void activeChanged(bool newState) {} 
private: 
    bool m_active; 
} 

class Button : public Controllable{ 
protected: 
    void activeChanged(bool newState){ /*do extra work*/ } 
public: 
    void input(Event & e); 
}; 

Với phương pháp này bạn đang giữ bên ngoài công cộng giao diện tách ra khỏi nội bảo vệ Giao diện dành cho các lớp con.

+0

Cảm ơn! Tôi không nghĩ đến việc sử dụng một phương pháp phi ảo theo cách này. Tôi có một số lớp cơ sở khác có thể hưởng lợi từ loại điều trị này. –

+0

'activeChanged' nên là riêng tư, không được bảo vệ, vì các lớp dẫn xuất sẽ không bao giờ cần phải gọi thực hiện lớp cơ sở, chỉ ghi đè lên nó. – ildjarn

+0

Minor "bug": Bạn sẽ gọi 'activeChanged()' mặc dù tên của nó thậm chí không thay đổi trạng thái (như 'm_active' đánh giá là true và bạn gọi' setActive (true) 'một lần nữa). – Mario

1

Làm cách nào để tạo setActive() không ảo nhưng thay vào đó thêm thành viên ảo thứ hai (ví dụ: onSetActive()) được gọi là setActive()?

6

Một cách để làm điều này là để xác định "tiền" và các phương pháp ảo "bài":

class Controllable{ 
public: 
    void setActive(bool state) { 
     preSetActive(m_active, state); 
     m_active = state; 
     postSetActive(m_active); 
    }; 
    virtual void input(Event & e) =0; 
protected: 
    virtual void preSetActive(bool oldState, bool newState) {} 
    virtual void postSetActive(bool newState) {} 
private: 
    bool m_active; 
} 

Lưu ý rằng phương pháp setActive()không ảo trong kỹ thuật này.

+0

Rất tuyệt. Có hai hàm trước và sau có thể là quá mức cần thiết trong trường hợp này, nhưng tôi có một vài lớp khác thì điều này hoàn hảo. Cảm ơn bạn! –

1

My 2 cents: chia hành vi của bạn giữa 2 nhiệm vụ:

virtual doActive(){}; //doNothing 
void setActive (bool state) { 
    m_active = state; 
    doActive(); 
} 
Các vấn đề liên quan