¿Hay una manera de añadir nuevos métodos a una clase, sin modificar la definición original de la clase (es decir, compilado lib contiene la clase y el correspondiente fichero .h) al igual que los métodos de extensión de clase C# 's?Extensión Clase C++
Respuesta
No. C++ no tiene esa capacidad.
Como se ha mencionado en otras respuestas, las soluciones comunes son:
- definir una clase derivada, tal vez con una fábrica de ocultar la clase de implementación real
- Definir una clase decorator
- definir funciones que operan en instancias de la clase
También se puede hacer por [envío doble] (http://en.wikipedia.org/wiki/Double_dispatch) – Bossliaw
No, no puede hacer esto en C++.
Si usted quiere lograr algo como esto tiene 2 opciones,
- Se puede heredar de la clase (si esto es una opción, puede que no sea legal que la clase no puede haber sido escrito a permitir que la herencia)
- usted puede escribir su propia clase de contenedor que tiene la misma interfaz + nuevos métodos y delegado a la que desea extender.
Yo prefiero el enfoque de delegación.
+1 por "favor composición sobre herencia" – Rob
Buena respuesta, pero no estoy seguro de que alguien haga preguntas como estos saben qué implementar cuando escucha términos como "heredar" o "delegar". –
@mh, probablemente no. pero ahora saben los términos correctos para poner en una búsqueda SO o Google – Glen
Lo siento, no. Una vez que su código está en obj, no puede cambiarlo. Si esto se puede hacer en VC, las clases parciales ya tendrían soporte. Sin embargo, hay una excepción, los métodos del operador se pueden extender usando funciones globales, muy parecido a cómo se implementa cout < < en STL.
métodos de extensión C# clase son en su mayoría de azúcar sintáctica. Obtiene la misma funcionalidad con funciones gratuitas (es decir, funciones con referencia o referencia constante a su clase como primer parámetro). Dado que esto funciona bien para el STL, ¿por qué no para su clase?
Claro que puedes:
template <typename Ext>
class Class: public Ext { /* ... */ };
Eso no quiere decir que sea el mejor enfoque sin embargo.
Generalmente no. Sin embargo, si la biblioteca no crea instancias de la clase que requieren su extensión y que son capaces de modificar todas las secciones de la aplicación que crean una instancia de la clase y requieren extensiones, hay una manera usted puede ir:
- Crea una función de fábrica que se llama en todos los lugares que requieren una instancia de la clase y devuelve un puntero a la instancia (google for Design Patterns Factory, ...).
- Crea una clase derivada con las extensiones que quieras.
- Haga que la función de fábrica devuelva su clase derivada en lugar de la clase original.
Ejemplo:
class derivedClass: public originalClass { /* ... */};
originalClass* createOriginalClassInstance()
{
return new derivedClass();
}
- Siempre que necesite acceder a las extensiones, es necesario emitir el reparto original de la clase derivada, por supuesto.
Esto es más o menos cómo implementar el método "heredar" sugerido por Glen. El método de la "clase contenedora con la misma interfaz" de Glen también es muy agradable desde un punto de vista teórico, pero tiene propiedades ligeramente diferentes que hacen que sea menos probable que funcione en su caso.
Hay una manera en que se puede hacer. Y eso es relajando un poco tus requisitos. En C++, la gente a menudo dice que la interfaz de una clase no consiste solo de sus funciones miembro, sino de todas las funciones que funcionan en la clase.
Es decir, las funciones no miembro a las que se puede asignar la clase como parámetro se deben considerar parte de su interfaz.
Por ejemplo, std::find()
o std::sort()
son parte de la interfaz de std::vector
, aunque no son miembros de la clase.
Y si acepta esta definición, entonces siempre puede extender una clase simplemente agregando funciones que no sean miembros.
No puede agregar métodos o datos físicamente al archivo de clase que está en forma binaria. Sin embargo, puede agregar métodos y datos (funcionalidad y estado) a los objetos de esa clase escribiendo clases de extensión. Esto no es sencillo y requiere una programación basada en Meta-Object-Protocol y Interface. Debe hacer mucho para lograr esto en C++, ya que no es compatible con Reflection de fábrica. En dicha implementación cuando consulta la interfaz implementada por su nueva clase de extensión a través del puntero de objeto de clase original, la implementación del metaobjeto devuelve ese puntero de interfaz a través del objeto metaclase para la clase de extensión que crea en tiempo de ejecución. Esta es la cantidad de marcos de aplicaciones de software personalizables (basados en complementos) que funcionan. Sin embargo, debe recordar que se deben escribir muchos otros mecanismos MOP para instanciar metaobjetos para todas las clases utilizando diccionarios en los que se describen las relaciones de objeto y dar los punteros de interfaz correctos para los objetos de clase originales y extendidos. CATIA V5 de Dassault Systemes está escrito en una arquitectura de este tipo llamada CAA V5, donde puede ampliar los componentes existentes escribiendo nuevas clases de extensión con la funcionalidad deseada.
En C++ puede usar 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 tenemos que escribir esto en C++ usando 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 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");
- 1. ¿Cómo extiendo una clase con los métodos de extensión C#?
- 2. C# extensión SoapExtension -
- 3. ctypes vs extensión C
- 4. Extensión de clase frente a la categoría de clase
- 5. ¿Qué es una clase de extensión?
- 6. ¿Métodos de extensión en una clase estática?
- 7. Java: extensión de clase de objeto
- 8. La extensión de una clase Singleton
- 9. C#: operador implícito y métodos de extensión
- 10. Extensión de PHP con C++
- 11. C# Método de extensión anterior
- 12. C# métodos de extensión ambiguos
- 13. Haciendo una extensión C a Python que requiere otra extensión
- 14. ¿Puedo agregar métodos de extensión a una clase estática existente?
- 15. Utilizando métodos de extensión C# de C++/CLI administrado
- 16. FormatProvider vs. método de extensión contra la nueva clase
- 17. Extensión de C++ Ruby con bibliotecas externas
- 18. diferencia entre la variable privada instancia y la propiedad en extensión de clase (Objective-C 2.0)
- 19. C# Métodos de extensión solo visibles y accesibles dentro de una clase ("privada")
- 20. ¿Hay alguna forma en C# para anular un método de clase con un método de extensión?
- 21. ¿Cómo puedo envolver una clase de C++ en la extensión de php?
- 22. ¿Cómo se escribe un método de extensión C# para una clase genéricamente escrita
- 23. Agregar un método de extensión a la clase de cadena - C#
- 24. método de extensión llamar a otro en la misma clase de extensión - ¿buen diseño?
- 25. ¿Extender la clase Enumerable en C#?
- 26. C extensión: <? and >? operadores
- 27. C# - Clasificación utilizando el Método de extensión
- 28. La extensión de Enum en C#
- 29. C# métodos de extensión similares en PHP?
- 30. Métodos de extensión F # en C#
Para referencia futura, esto se llama 'Monkey patching'. – LiraNuna