2010-05-28 22 views

Respuesta

0

Con respecto a los métodos de extensión de C#: No directamente. C++ tiene menos necesidad de estas cosas porque C++ admite funciones gratuitas. Nunca utilicé Objective-C, así que no puedo comentar allí.

1

C++ no tiene clases selladas ni herencia de clase única, por lo que en la mayoría de los casos puede subclasificar la clase base. Hay maneras creativas de hacer que una clase no sea heredable, pero son pocas y están muy alejadas. En general, C++ no tiene los problemas C# que dieron origen a los métodos de extensión.

C no está orientado a objetos, por lo que la pregunta no se aplica realmente.

+0

¿Qué "problemas en C#" dieron a luz a los métodos de extensión? Los métodos de extensión existen únicamente para soportar LINQ, una característica que C++ no tiene en ninguna descripción. –

+0

Clases selladas y clase única heredables. Además de los métodos de extensión LINQ, proporcionan la capacidad de extender la funcionalidad de la clase, lo que no es posible cuando la clase está sellada (como 'cadena'). De manera similar, la restricción de heredar una clase limita tu capacidad de agregar mixins. –

+3

Sí, pero las clases en C++ están efectivamente selladas cuando no tienen destructores virtuales, por lo que no veo cómo C++ no tiene el mismo problema. –

0

¿Se puede utilizar una interfaz? Los métodos de extensión son una manera fácil de evitar la creación de subclases, pero se vuelven semiinutilizables cuando se usan técnicas de OO adecuadas. La razón por la que se usan tanto con Linq es por lo que el equipo VS no tuvo que ir y actualizar el código que probablemente rompería muchas aplicaciones heredadas.

Por MSDN: "En general, recomendamos implementar métodos de extensión con moderación y solo cuando sea necesario. Siempre que sea posible, el código de cliente que debe extender un tipo existente debe hacerlo creando un nuevo tipo derivado del existente tipo."

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

+0

Aunque tener una LinqList me haría sonreír. –

3
No

realmente. No es la forma C++ de tratar clases como esta.

Entre otros, Meyers sostiene que es mejor tener una clase pequeña con el conjunto mínimo de operaciones que la hacen completamente útil. Si desea expandir el conjunto de características, puede agregar un espacio de nombre de utilidad (por ejemplo, espacio de nombres ClassUtil) que contiene funciones de utilidad no miembro que operan en esa clase mínima. Es fácil agregar funciones a un espacio de nombres desde cualquier lugar.

Puede consultar un debate sobre el tema here.

+1

Las funciones gratuitas SON el camino a seguir. –

23

C++ tiene funciones gratuitas, pero a veces los métodos de extensión funcionan mejor cuando anida muchas funciones juntas. Echar un vistazo a este código C#:

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

Si escribimos esto en C++ utilizando la función gratuita que se vería así:

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

Esto no sólo es difícil de leer, pero es difícil de escribir. La forma común de resolver esto es crear lo que se llama una función pipable. Estas funciones se crean al sobrecargar el operador de tubería | (que en realidad es el operador u). El código anterior podría escribirse así:

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

Lo cual es mucho más fácil de leer y escribir. Muchas bibliotecas usan la función pipable para los rangos, pero también podría expandirse a otras clases. Boost lo usa en su biblioteca range, pstade oven lo usa, y también esta biblioteca C++ linq lo usa también.

Si desea escribir su propia función pipable, amplíe explica cómo hacerlo here. Sin embargo, otras bibliotecas proporcionan adaptadores de funciones para facilitarlo.El huevo Pstade tiene un pipable adaptor, y linq proporciona el adaptador range_extension para crear una función pipable para rangos como mínimo.

mediante LINQ, primero acaba de crear su función como un objeto función como esta:

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

A continuación se inicializa la función usando la inicialización estático como sigue:

range_extension<contains_t> contains = {}; 

A continuación, puede utilizar su función pipable como esta:

if (numbers | contains(5)) printf("We have a 5"); 
Cuestiones relacionadas