7

Sự khác nhau giữa NVI (Non-Virtual Interface) và các mẫu Template Method là gì?C++: Sự khác biệt giữa mẫu phương pháp mẫu và NVI?

Chúng có vẻ rất giống nhau và tôi đã đọc cả về cơ bản chúng giống nhau và chúng khác biệt một cách tinh tế với Mẫu bằng cách nào đó tổng quát hơn.

+1

Tôi sẽ không sử dụng liên kết wikipedia làm tài liệu tham khảo, việc sử dụng khóa của chúng dễ vỡ khi đối mặt với ngoại lệ ... –

Trả lời

11

NVI là một thành ngữ, Phương thức mẫu là mẫu. NVI là một triển khai thực hiện Mẫu Khuôn mẫu Khuôn mẫu bằng cách sử dụng công văn động trong C++; cũng có thể tạo các phương thức mẫu trong C++ bằng cách sử dụng lập trình meta mẫu để loại bỏ công văn động.

Mẫu tổng quát hơn một thành ngữ và các ngôn ngữ có thể sử dụng các thành ngữ khác nhau để triển khai mẫu.

+1

Vì vậy, bạn đang nói rằng NVI cơ bản là một ngôn ngữ thực hiện cụ thể của mẫu Phương thức mẫu và hơn thế nữa không có sự khác biệt thực sự? Làm thế nào bạn sẽ sử dụng các mẫu C++ để đạt được kết quả tương tự? –

+0

@Robert S. Barnes Theo như tôi thấy, không có cách nào rõ ràng khi sử dụng các mẫu C++ làm phương thức mẫu. Phương thức mẫu nói 'làm điều này, sau đó làm điều khác', và trong khi bạn có thể tạo một hàm cho một hoặc một thứ khác để làm, thì không có mối quan hệ thực sự nào với các tham số kiểu mà các mẫu C++ cung cấp cho bạn. –

+0

Tôi đoán tôi vẫn chưa hiểu ý của bạn ở đây: "cũng có thể tạo các phương thức mẫu trong C++ bằng cách sử dụng lập trình meta mẫu để loại bỏ công văn động." –

8

Như đã nói, NVI là một thành ngữ progamming, liên quan đến một loại ngôn ngữ. Nó được thúc đẩy bởi Herb Sutter số những người khác, bởi vì nó giúp các hợp đồng thực thi:

  • bất biến lớp
  • hợp đồng function (khẳng định qua các thông số thông qua và giá trị trả về tạo ra)
  • hoạt động lặp đi lặp lại (như khai thác gỗ)
  • kiểm soát đối với trường hợp ngoại lệ được tạo ra (xấu ý tưởng mặc dù;))

tuy nhiên, việc thực hiện trên thực tế có thể khác nhau đáng kể, ví dụ một ví dụ khác của NVI thực hiện là kết hợp nó với Pimpl:

class FooImpl; 

class Foo 
{ 
public: 
    enum type { Type1, Type2 }; 

    Foo(type t, int i, int j); 

    int GetResult() const; 

private: 
    FooImpl* mImpl; 
}; 

Và đối với việc thực hiện:

struct FooImpl 
{ 
    virtual ~FooImpl(); 
    virtual int GetResult() const; 
}; 

class FooType1: public FooImpl 
{ 
public: 
    FooType1(int i, int j); 
    virtual int GetResult() const; 
private: 
    /// ... 
}; 

Tôi luôn thấy rằng nó được truyền đạt điểm tốt hơn. Bạn đã tìm ra nó chưa?

Điểm chính là virtual là chi tiết triển khai. Và việc hiển thị chi tiết triển khai trong giao diện là một ý tưởng tồi, bởi vì bạn có thể muốn thay đổi chúng.

Ngoài ra, chi tiết triển khai có xu hướng lộn xộn với khả năng tương thích nhị phân. Ví dụ, thêm một phương thức virtual mới trong một lớp có thể thay đổi cách bố trí của bảng ảo (kỹ thuật triển khai chung) và do đó tạo ra khả năng tương thích nhị phân. Trên gcc, bạn cần phải chắc chắn rằng bạn thêm nó cuối cùng (trong số ảo) nếu bạn muốn duy trì tính tương thích.

Bằng cách sử dụng kết hợp NVI + Pimpl ở trên, không có virtual ở tất cả (thậm chí không riêng tư) trong lớp được hiển thị. Bố cục bộ nhớ tương thích ngược và tiến. Chúng tôi đã đạt được khả năng tương thích nhị phân.

Ở đây, chúng tôi sử dụng một số mô hình cùng một lúc:

  • Template Method
  • Chiến lược (kể từ khi chúng ta có thể trao đổi con trỏ theo ý muốn)
  • Factory (để quyết định thực hiện chúng tôi nhận)
+0

+1 cho "chi tiết triển khai ảo" và xem xét ABI. – neuro

+0

+1. Tuy nhiên, tôi không đồng ý với bạn về việc tạo các lớp giống pimpl riêng biệt cho giao diện ảo. Nhược điểm rõ ràng nhất là nó tăng gấp đôi số lớp cần thiết. Ngoài ra nếu FooImpl không mờ đục, nó có thể lôi kéo mọi người sử dụng nó trực tiếp và bỏ qua Foo. Tuy nhiên, nó không chắc rằng nó sẽ mờ đục vì điểm của các NVI là cho phép mọi người ghi đè lên việc triển khai ảo, vì vậy FooImpl sẽ phải được truy cập công khai. Mặc dù nó có nhược điểm riêng của nó, tôi nghĩ rằng việc thực hiện NVI trong một lớp và tránh các chức năng ảo công cộng cùng nhau là một cách tiếp cận tốt hơn. – stinky472

+0

Nó cũng là một chính sách dễ thực thi hơn: không có chức năng ảo công cộng nào khác với chức năng tạo ra các trường hợp đặc biệt cho các lớp giống như pimpl cung cấp giao diện ảo công khai. – stinky472

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