2010-05-28 34 views

Trả lời

0

Đối với các phương pháp mở rộng của C#: Không trực tiếp. C++ có ít nhu cầu hơn cho những thứ này vì C++ hỗ trợ các chức năng miễn phí. Tôi chưa từng sử dụng Objective-C nên tôi không thể bình luận ở đó.

1

C++ không có lớp được đóng dấu hoặc thừa kế lớp đơn, vì vậy trong hầu hết trường hợp, bạn có thể phân lớp lớp cơ sở. Có những cách sáng tạo để làm cho một lớp học không thể kế thừa, nhưng chúng rất ít và xa ở giữa. Nói chung, C++ không có vấn đề C# nào đã sinh ra các phương thức mở rộng.

C không phải là đối tượng được định hướng, vì vậy câu hỏi không thực sự áp dụng.

+0

"Vấn đề gì trong C#" đã sinh ra các phương pháp mở rộng? Các phương thức mở rộng chỉ tồn tại để hỗ trợ LINQ, một tính năng C++ không có trong bất kỳ mô tả nào. –

+0

Các lớp học kín và lớp đơn có thể kế thừa. Ngoài các phương thức mở rộng LINQ cung cấp khả năng mở rộng chức năng của lớp, điều này là không thể khi lớp được niêm phong (như 'chuỗi'). Tương tự, hạn chế kế thừa một lớp sẽ giới hạn khả năng thêm mixin của bạn. –

+3

Có, nhưng các lớp trong C++ được niêm phong hiệu quả khi chúng không có các trình phá hủy ảo, vì vậy tôi không thấy cách C++ không có cùng một vấn đề. –

0

Bạn có thể sử dụng giao diện không? Các phương thức mở rộng là một cách dễ dàng để tránh phân lớp con, nhưng chúng được kết xuất bán vô dụng khi các kỹ thuật OO thích hợp được sử dụng. Lý do mà chúng được sử dụng với LINQ rất nhiều là do đó nhóm VS không phải đi và cập nhật mã mà rất có thể sẽ phá vỡ rất nhiều ứng dụng kế thừa.

Mỗi MSDN: "Nói chung, chúng tôi khuyên bạn nên triển khai các phương pháp mở rộng một cách tiết kiệm và chỉ khi bạn phải làm vậy. Bất cứ khi nào có thể, mã khách hàng phải mở rộng loại hiện có phải làm như vậy bằng cách tạo loại mới có nguồn gốc từ hiện tại kiểu."

http://msdn.microsoft.com/en-us/library/bb383977.aspx

+0

Mặc dù có một LinqList sẽ làm cho tôi mỉm cười. –

3

Không thực sự. Nó không phải là cách C++ để xử lý các lớp như thế này.

Trong số những người khác, Meyers cho rằng tốt nhất nên có một lớp học nhỏ với tập hợp hoạt động tối thiểu làm cho nó hoàn toàn hữu ích. Nếu bạn muốn mở rộng bộ tính năng, bạn có thể thêm một vùng tên tiện ích (ví dụ: không gian tên ClassUtil) có chứa các hàm tiện ích không phải thành viên hoạt động trên lớp tối thiểu đó. Thật dễ dàng để thêm các hàm vào một vùng tên từ bất kỳ đâu.

Bạn có thể kiểm tra một cuộc thảo luận về chủ đề here.

+1

Các chức năng miễn phí LÀ cách đi. –

23

C++ có chức năng miễn phí, nhưng đôi khi các phương thức mở rộng hoạt động tốt hơn khi bạn lồng ghép nhiều hàm với nhau. Hãy nhìn vào mã này C#:

var r = numbers.Where(x => x > 2).Select(x => x * x); 

Nếu chúng ta viết những dòng này trong C++ sử dụng chức năng miễn phí nó sẽ trông như thế này:

auto r = select(where(numbers, [](int x) { return x > 2; }), [](int x) { return x * x; }); 

Không chỉ là khó khăn này để đọc, nhưng rất khó để viết. Cách phổ biến để giải quyết điều này là tạo ra cái được gọi là hàm pipable. Các chức năng này được tạo ra bằng cách quá tải toán tử đường ống | (chỉ thực sự là toán tử hoặc toán tử). Vì vậy, mã ở trên có thể được viết như sau:

auto r = numbers | where([](int x) { return x > 2; }) | select([](int x) { return x * x; }); 

Đọc và viết dễ dàng hơn nhiều. Nhiều thư viện sử dụng hàm pipable cho các phạm vi, nhưng nó có thể được mở rộng đến các lớp khác. Boost sử dụng nó trong thư viện range, pstade oven sử dụng thư viện này và thư viện C++ linq cũng sử dụng thư viện này.

Nếu bạn muốn viết hàm pipable của riêng mình, hãy giải thích cách thực hiện điều đó here. Các thư viện khác, tuy nhiên, cung cấp các bộ điều hợp chức năng để làm cho nó dễ dàng hơn.Trứng pstade có pipable adaptor và LINQ cung cấp bộ điều hợp range_extension để tạo một hàm pipable cho phạm vi ít nhất.

Sử dụng LINQ, trước tiên bạn chỉ cần tạo chức năng của bạn như một đối tượng hàm như thế này:

struct contains_t 
{ 
    template<class Range, class T> 
    bool operator()(Range && r, T && x) const 
    { return (r | linq::find(x)) != boost::end(r); }; 
}; 

Sau đó, bạn khởi tạo chức năng sử dụng khởi tạo tĩnh như thế này:

range_extension<contains_t> contains = {}; 

Sau đó, bạn có thể sử dụng của bạn chức năng pipable như thế này:

if (numbers | contains(5)) printf("We have a 5"); 
Các vấn đề liên quan