2011-11-07 26 views
8

Giả sử tôi có một lớp có thể sử dụng các loại hàm khoảng cách khác nhau (khoảng cách Euclide, vv) để thực hiện một số so sánh. Tôi đã thực hiện các chức năng như là lớp con của một cách lớp:Sự khác biệt giữa việc chọn một phân lớp thông qua tham số mẫu hoặc tạo biến thành viên

class Distance; 
class EuclideanDistance : public Distance; 
class OtherDistance : public Distance; 

Dường như để chọn loại khoảng cách để sử dụng, tôi có thể làm:

template <typename TDistance> 
class MyClass; 

và nhanh chóng nó với:

MyClass<EuclideanDistance> instance; 

hoặc thực hiện điều tương tự với:

class MyClass 
{ 
public: 
Distance* myDistanceFunction; 
} 

và instantiating nó với

MyClass instance; 
instance.myDistanceFunction = new EuclideanDistance; 

có lợi thế nào của phương pháp này so với phương pháp khác không?

Cảm ơn,

David

Trả lời

6

Hiệp hội (tức là giải pháp không có mẫu) thích hợp hơn vì nó cung cấp cho bạn sự linh hoạt hơn, cho phép bạn thay đổi triển khai khoảng cách trong thời gian chạy, tạo ra thông báo lỗi sạch hơn và tệp đối tượng sạch hơn (ít biểu tượng hơn).

Ngoài ra, các lớp được tạo từ mẫu được tham số với các loại khác nhau (triển khai khoảng cách) sẽ được coi là các loại khác nhau và sẽ không thể hoán đổi cho nhau: MyClass<EuclideanDistance> là loại khác với MyClass<MinkowskiDistance>. Điều này sẽ buộc bạn phải thực hiện tất cả các chức năng hoạt động trên các mẫu MyClass và cuối cùng sẽ dẫn đến độ phức tạp cao hơn mà không có lợi ích bổ sung.

Mẫu nên được sử dụng khi bạn cần thư giãn an toàn loại ngôn ngữ, ví dụ khi bạn viết một lớp nên hoạt động trên một số loại không liên quan (không bắt nguồn từ lớp cơ sở/giao diện chung) mà dù sao cũng hoạt động theo cách tương tự (ví dụtất cả đều có chức năng thành viên kwak()). Điều này được gọi là duck-typing: các loại chính thức không liên quan nhưng tất cả đều thể hiện các thuộc tính tương tự.

Trong trường hợp bạn bị ngăn không cho đảm bảo rằng tất cả triển khai khoảng cách lấy được từ một lớp cơ sở chung/giao diện, bạn có thể cần phải sử dụng mẫu. Nếu không, thích sự kết hợp đơn giản và linh hoạt hơn.

2

Cựu sửa khoảng cách số liệu cho các lớp tại thời gian biên dịch, trong khi thứ hai thực hiện nó tại thời gian chạy. Trước đây có khả năng hiệu quả hơn bởi vì nó cho phép trình biên dịch tối ưu hóa các phần của nó đi, trong khi thứ hai có thể linh hoạt hơn.

+0

Trong phương pháp thứ hai - có cách nào để tạo đối tượng thứ hai cùng loại với đối tượng đầu tiên không? –

+0

@DavidDoria: bạn có ý nghĩa gì? Một 'MyClass', một' EuclideanDistance'? –

+0

Một đối tượng khác có cùng kiểu như myDistanceFunction bên trong MyClass. –

4

Vâng, ngoài thời gian biên dịch so với vấn đề thời gian chạy, sự khác biệt lớn nhất đã không được chấp nhận bởi mã đã tồn tại từ trước của bạn. Sử dụng mẫu sẽ cho phép bạn sử dụng bất kỳ loại nào hỗ trợ hoạt động phổ biến (ví dụ: getDistance) mà không cần chúng phải từ cùng một chế độ thừa kế. Điều này có nghĩa là khoảng cách Euclide và lớp khác của bạn có thể hoàn toàn khác, nhưng vẫn có thể sử dụng được trong mẫu miễn là chúng hỗ trợ tập hợp con các thành viên mà mẫu đã sử dụng.

+0

Tôi thấy - vì vậy tôi sẽ chỉ có EuclideanDistance và OtherDistance là các lớp riêng biệt, không bắt nguồn từ bất kỳ lớp Distance cha mẹ nào. –

+0

Nó sẽ là hoàn toàn có thể :) Mẫu cho phép lập trình chung, xử lý những thứ có giao diện ngầm tương tự (những thứ theo yêu cầu của mẫu) như nhau. Đó là khái niệm tương tự như cách STL thường cho phép bạn vượt qua trong một hàm functor (một đối tượng hàm) hoặc một hàm thực tế - mẫu sử dụng hàm được truyền trong hàm hoặc hàm functor không quan tâm nó là gì, nó chỉ quan tâm đến việc truyền vào tham số có thể gọi với cú pháp(). Vì vậy, các mẫu được rất nhiều linh hoạt hơn so với thừa kế thừa kế (nhưng chắc chắn có ưu và khuyết điểm cho cả hai). –

1

Thừa kế công khai có nghĩa là IS-A. Là một EuclideanDisatance tương thích với một "LorentzDistance" hoặc "QuaternionDistance" (hoặc bất cứ điều gì) trong bất kỳ cách có ý nghĩa? Có phải cả hai "khoảng cách" theo nghĩa là một số mã ở đâu đó sẽ vui vẻ sử dụng một trong một cách không tầm thường (nghĩa là, một thứ khác ngoài việc in giá trị, v.v ...)? Tôi đoán là không, không phải vậy.

Vì vậy, bạn muốn dùng Generics, không phải thừa kế. Các mẫu là một lời hứa đơn giản: hai thứ "trông giống như" mỗi cú pháp khác.

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