2010-05-28 14 views

Odpowiedz

0

W odniesieniu do metod rozszerzenia C#: Nie bezpośrednio. C++ ma mniejsze zapotrzebowanie na te rzeczy, ponieważ C++ obsługuje bezpłatne funkcje. Nigdy nie używałam Objective-C, więc nie mogę tam komentować.

1

C++ nie ma zamkniętych klas ani dziedziczenia pojedynczej klasy, więc w większości przypadków można podklasować klasę podstawową. Istnieją kreatywne sposoby, aby uczynić klasę nie-dziedziczną, ale są one nieliczne i odległe. Ogólnie C++ nie ma problemów z C#, które dały początek metodom rozszerzania.

C nie jest zorientowany obiektowo, więc pytanie tak naprawdę nie ma zastosowania.

+0

Co "problemy w języku C#" dały początek metodom rozszerzania? Metody rozszerzeń istnieją wyłącznie w celu obsługi LINQ, a funkcja C++ nie ma żadnego opisu. –

+0

Klasy szczelne i jedna klasa dziedziczna. Poza metodami LINQ Extension można rozszerzyć funkcjonalność klasy, co nie jest możliwe, gdy klasa jest zamknięta (np. 'String'). Podobnie ograniczenie dziedziczenia jednej klasy ogranicza twoją zdolność do dodawania mixinów. –

+3

Tak, ale klasy w C++ są skutecznie zapieczętowane, gdy nie mają wirtualnych destruktorów, więc nie widzę, jak C++ nie ma tego samego problemu. –

0

Czy możesz użyć interfejsu? Metody rozszerzania są łatwym sposobem na uniknięcie tworzenia podklas, ale stają się one częściowo bezużyteczne, gdy stosowane są odpowiednie techniki OO. Powodem, dla którego są one używane z Linqem jest to, że zespół VS nie musiał iść i aktualizować kod, który najprawdopodobniej zepsułby wiele starszych aplikacji.

Na MSDN: "Ogólnie zaleca się oszczędne wdrażanie metod rozszerzeń i tylko wtedy, gdy jest to konieczne. Jeśli to możliwe, kod klienta, który musi rozszerzyć istniejący typ, powinien to zrobić, tworząc nowy typ pochodzący z istniejącego. rodzaj."

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

+0

Chociaż posiadanie LinqList sprawiłoby, żebym się uśmiechnął. –

3

Niezupełnie. To nie jest sposób C++ na traktowanie takich klas.

Między innymi, Meyers twierdzi, że najlepiej jest mieć małą klasę z minimalnym zestawem operacji, które sprawiają, że jest ona w pełni użyteczna. Jeśli chcesz rozwinąć zestaw funkcji, możesz dodać przestrzeń nazw narzędzi (np. Przestrzeń nazw ClassUtil), która zawiera funkcje pomocnicze nie będące członkami, które działają na tej minimalnej klasie. Łatwo jest dodać funkcje do przestrzeni nazw z dowolnego miejsca.

Możesz sprawdzić dyskusję na ten temat: here.

+1

Bezpłatne funkcje SĄ do zrobienia. –

23

C++ ma wolne funkcje, ale czasami metody rozszerzeń działają lepiej, gdy zagnieżdżymy wiele funkcji. Spójrz na ten kod C#:

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

Jeśli piszemy to w C++ z użyciem wolnego funkcji będzie wyglądać następująco:

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

Nie tylko jest to trudne do odczytania, ale trudno pisać. Najczęstszym sposobem rozwiązania tego problemu jest stworzenie tak zwanej funkcji potokowej. Te funkcje są tworzone przez przeciążanie operatora rurki | (który jest po prostu operatorem lub). Tak więc powyższy kod może być napisany w następujący sposób:

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

Znacznie łatwiejsze do odczytania i napisania. Wiele bibliotek korzysta z funkcji pipetowania dla zakresów, ale może również zostać rozszerzone na inne klasy. Funkcja Boost używa go w swojej bibliotece, a także korzysta z niej również ta biblioteka C++ linq.

Jeśli chcesz napisać własną funkcję pipisingu, boost wyjaśnij, jak to zrobić here. Inne biblioteki jednak zapewniają adaptery funkcjonalne, aby ułatwić.Pstade egg ma numer pipable adaptor, a linq zapewnia adapter range_extension, aby utworzyć funkcję pipetowania dla zakresów co najmniej.

użyciu LINQ, najpierw tylko utworzyć funkcję jako obiekt funkcjonował jak ten:

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

Następnie należy zainicjować funkcję używając inicjalizacji statycznej tak:

range_extension<contains_t> contains = {}; 

Następnie można używać swojego funkcja potokowa taka jak:

if (numbers | contains(5)) printf("We have a 5"); 
Powiązane problemy