2009-03-19 19 views
8

tôi thấy đoạn mã sau trong thư viện:Ưu điểm của cuộc gọi hàm gián tiếp này là gì?

class Bar { 
public: 
    bool foo(int i) { 
    return foo_(i); 
    } 
private: 
    virtual bool foo_(int i) = 0; 
}; 

Bây giờ tôi đang tự hỏi: Tại sao bạn sẽ sử dụng gián tiếp này? Có thể có bất kỳ lý do tại sao ở trên sẽ là tốt hơn so với phương án đơn giản:

class Bar { 
public: 
    virtual bool foo(int i) = 0; 
}; 

Trả lời

10

Đây là số Non-Virtual Interface Idiom (NVI). Trang đó của Herb Sutter có một chút chi tiết về nó. Tuy nhiên, tính khí những gì bạn đọc ở đó với những gì C++ FAQ Lite nói herehere.

Ưu điểm chính của NVI là tách giao diện khỏi triển khai. Một lớp cơ sở có thể thực hiện một thuật toán chung và trình bày nó với thế giới trong khi các lớp con của nó có thể thực hiện các chi tiết của thuật toán thông qua các hàm ảo. Người dùng bên ngoài được bảo vệ khỏi những thay đổi trong các chi tiết thuật toán, đặc biệt nếu sau này bạn quyết định bạn muốn thêm mã tiền xử lý và trước.

Những bất lợi rõ ràng là bạn phải viết thêm mã. Ngoài ra, private chức năng ảo gây nhầm lẫn cho rất nhiều người. Nhiều lập trình viên nghĩ nhầm rằng bạn không thể ghi đè chúng. Herb Sutter có vẻ giống như private virtuals, nhưng IMHO nó hiệu quả hơn trong thực tế để làm theo khuyến nghị của C++ FAQ Lite và làm cho chúng protected.

3

này thường được gọi là một cặp Template-Hook (còn được gọi Hotspot), đặt ra bởi Wolfgang Pree.

Xem PDF, PowerPoint, HTML

Một lý do này để thực hiện các gián tiếp như bạn gọi nó là những thứ thường có thể/phải là thiết lập trước một phương pháp, và một số cleaing bài một gọi phương thức. Trong lớp con bạn chỉ cần cung cấp các hành vi cần thiết mà không làm thiết lậpsạch ...

0

Nếu một lớp con có thể thay đổi định nghĩa của foo_ ?, nhưng người tiêu dùng cần một hàm tĩnh (đối với hiệu quả) ? Hoặc cho một mô hình ủy quyền?

2

Đây là mẫu mẫu. Phương thức foo chứa mã phải được thực thi bởi tất cả các lớp con. Nó có ý nghĩa hơn khi bạn nhìn vào nó như thế này:

class Bar { 
public: 
    bool foo(int i) { 
    // Setup/initialization/error checking/input validation etc 
    // that must be done for all subclasses 
    return foo_(i); 
    } 
private: 
    virtual bool foo_(int i) = 0; 
}; 

Nó đẹp hơn thay thế, đó là cố gắng nhớ gọi mã chung trong mỗi phân lớp riêng lẻ. Chắc chắn, ai đó làm cho một phân lớp nhưng quên gọi mã phổ biến, dẫn đến bất kỳ số lượng các vấn đề.

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