Proyecto del asesor - página 5

 

George Merts
Стандартный CObject - это "объект списка или сортированного массива". CMyObject - это CObject, имеющий определенный тип, и содержащий некоторое значение, данное при его создании. Этот объект мне понадобился всвязи с повсеместным приведением объектов к базовому абстрактному классу - чтобы понимать по указателю, на какой именно объект "на самом деле" указывает. Тип CMyObject - устанавливается как раз той самой функцией SetMyObjectType(). Эта функция в обязательном порядке вызывается в конструкторах любых наследников от CMyObject, чтобы назначить идентификатор класса, к которому принадлежит создаваемый объект.

Su constructor es abierto y sin parámetros:

class CTradeHistoryI: public CMyObject
{
public:
   void CTradeHistoryI() {    SetMyObjectType(MOT_TRADE_HISTORY_I); };
}

Esto significa que un heredero puede o no establecer su propio tipo. Así que si te olvidas de llamar al método SetMyObjectType dentro del descendiente, estás jodido.

¿Qué puedes hacer?

1. Debe cerrar el constructor desde fuera de la creación:

class CTradeHistoryI: public CMyObject
{
protected:
   void CTradeHistoryI() {    SetMyObjectType(MOT_TRADE_HISTORY_I); };
}

En este caso, sólo los descendientes de CTradeHistoryI podrán crear una instancia, lo que significa que no será necesario el tipo MOT_TRADE_HISTORY_I. Tenga en cuenta que el tipo MOT_TRADE_HISTORY_I nunca existe en la realidad, porque CTradeHistoryI es una interfaz, y no puede haber ninguna instancia de este tipo. Es decir, al cerrar el constructor resolvemos la contradicción - descripción del tipo que no existe.

2. Establezcamos el requisito de tipificación explícita en el momento de la creación de la instancia:

enum ENUM_OBJ_TYPE
{
   OBJ_HIST_DEALS_LIST,
   OBJ_HIST_ORDERS_LIST
   ...
};

class CTradeHistoryI: public CMyObject
{
private:
   ENUM_OBJ_TYPE   m_obj_type;
protected:
   CTradeHistoryI(ENUM_OBJ_TYPE obj_type)
   {
      m_obj_type = obj_type;
   }
public:
   ENUM_OBJ_TYPE ObjectType(void) const
   {
      return m_obj_type;
   }
};

class CTradeHistory : public CTradeHistoryI
{
public:
   CTradeHistory(void);
};

CTradeHistory::CTradeHistory(void) : CTradeHistory(OBJ_HIST_DEALS_LIST)
{
}

Eso es todo, ahora ningún descendiente puede crearse a sí mismo sin una especificación de tipo explícita.

 
Vasiliy Sokolov:

¿Por qué reinventar la rueda en forma de CMyObject, cuando existe un CObject estándar que todo el mundo entiende?

No sé qué de bueno has encontrado en MQL CObject. Dos punteros innecesarios metidos en cada objeto = 16 bytes perdidos + sobrecarga innecesaria en la asignación de memoria e inicialización de estos punteros. La POO en sí misma ralentiza el rendimiento, y si se añaden soluciones tan inútiles...
 
Alexey Navoykov:
No sé qué de bueno has encontrado en el CObject de MQL. Dos punteros innecesarios metidos en cada objeto = 16 bytes desperdiciados + sobrecarga innecesaria en la asignación de memoria e inicialización de estos punteros. La POO en sí misma ralentiza el rendimiento, y si se añaden soluciones tan inútiles...

Primero aprende OOP, luego lo discutiremos. La inicialización de m_prev, m_next no ocurre en el caso general.

 
Vasiliy Sokolov:

Primero aprende OOP, luego lo discutiremos. La inicialización de m_prev, m_next en general no ocurre si algo.

Sólo después de ti.

Así que, para que se sepa, la inicialización de los punteros en MQL se realiza siempre.

 
Vasiliy Sokolov:

Su constructor es abierto y sin parámetros:

Esto significa que un heredero puede o no establecer su propio tipo. Así que si te olvidas de llamar al método SetMyObjectType dentro del descendiente, estás jodido.

¿Qué puedes hacer?

...

Sí, efectivamente en algunos casos me olvido de especificar SetMyObjectType() - y los objetos se crean con el tipo CMyObject por defecto.

Y el método de solución es bueno.

Se aceptan sugerencias.

Sin embargo, no me gusta el constructor protegido.

 
George Merts:

Sí, efectivamente, en algunos casos me olvido de especificar SetMyObjectType() - y los objetos se crean con el tipo CMyObject por defecto.

Y el método de solución es bueno.

Se aceptan sugerencias.

Aunque no me gusta el constructor de protección.

El constructor protegido sólo complica la vida a aquellas clases que heredan directamente del padre con dicho constructor. Pero a nivel de usuario, se pueden crear objetos derivados sin dudarlo y con total libertad.

Por lo tanto, no debe observarse el inconveniente.

Y no hay otras opciones en MQL, porque no hay sistema de comprobación de tipos, o mejor dicho, existe pero de forma poco desarrollada, por lo que, tenemos que proteger el tipo ocultando un constructor.

 
Alexey Navoykov:
No sé qué de bueno has encontrado en el CObject de MQL. Dos punteros innecesarios metidos en cada objeto = 16 bytes perdidos + sobrecarga innecesaria en la asignación de memoria e inicialización de estos punteros. La POO en sí misma ralentiza el rendimiento, y cuando se le añaden soluciones tan inútiles...

¿Por qué "inútil"? La sobrecarga es, en mi opinión, muy pequeña, y obviamente vale la pena la comodidad que ofrece CObject a la hora de organizar listas y matrices ordenadas.

Si tenemos que perseguir microsegundos y bytes, entonces, por supuesto, tiene sentido pensar si estos mismos "bytes perdidos" no suponen demasiados recursos. Pero, como muestra mi práctica, la comodidad de la escritura y el mantenimiento del código es mucho más importante.

Por cierto, recientemente he participado en la optimización del código - mis Asesores Expertos eran de alguna manera demasiado lentos en el probador. La función más lenta fue la de actualización de datos. Así que traté de disminuir llamando a este refresco en todos los sentidos. Pero, recientemente se ha hecho posible perfilar el código en el probador. Y para mi gran sorpresa, vi que la mayor parte del tiempo de mi Expert Advisor se gasta en la función de preguntar el estado del terminal (que no necesitaba (casi)) (se realizaba en cada refresco, y simplemente se hacía "a la vez" con el resto). Y sobre todo - desperdiciado en la función que solicita la memoria libre. ¡Un ligero cambio en el código, para que el estado del terminal se consulte sólo una vez al inicio y luego en los refrescos - sólo cuando se señala explícitamente - aceleró las pruebas en más de tres veces!

Así que la "sobrecarga innecesaria" puede perderse en absoluto donde la buscamos.

 
George Merts:

Así que la "sobrecarga innecesaria" puede no perderse en absoluto donde la buscamos.

No discutas con él. Su único objetivo es despotricar. Nunca demostrarás nada a gente como él. La mejor estrategia para lidiar con estos personajes es ignorarlos totalmente.
 
George Merts:

¿Por qué "inútil"? La sobrecarga es, en mi opinión, muy pequeña, y claramente vale la pena la comodidad que CObject proporciona en la organización de listas y matrices ordenadas.

Estas "comodidades" se implementan de forma exagerada. ¿Qué tipo de lista cambia algo en sus objetos? En esencia, resulta que no se pueden poner objetos constantes en una lista. O imagina tu objeto en una lista de este tipo, lo envías a una función, que también lo pone en su lista, y entonces recibes tu objeto de vuelta con prev y next cambiados, y el juego comienza...

En el mundo civilizado las listas se implementan mediante objetos auxiliares Node, que almacenan los punteros necesarios. Y tocar los propios objetos del usuario es una tontería. Así que no es sólo la sobrecarga, sino la incorrección fundamental de todo ello. Los desarrolladores acaban de improvisar algo rápido, y tú estás contento como si debiera ser así.

 
Alexey Navoykov:

Estas "comodidades" se aplican a través de un solo lugar. ¿Qué tipo de lista es la que cambia algo de sus objetos? En esencia, no se pueden poner objetos constantes en una lista. O imagina la situación, cuando envías tu objeto en tal lista a una función, que también lo pone en su lista, y entonces recibes tu objeto de vuelta con prev y next cambiados, y el juego comienza ...

En el mundo civilizado las listas se implementan mediante objetos auxiliares Node, que almacenan los punteros necesarios. Y no tiene sentido tocar los propios objetos del usuario. Así que no es sólo la sobrecarga, sino la incorrección fundamental de todo ello. Los desarrolladores acaban de improvisar algo a corto plazo y tú te alegras como si tuviera que ser así.

Pues sí, no se pueden poner objetos constantes en una lista.

Sin embargo, utilizo constantemente la funcionalidad de CObject y ninguno de mis críticos sugirió nada siquiera similar a los objetos de arrays y listas de la Biblioteca Estándar.

"La forma en que se deben hacer las cosas" es el grito de todos. Pero para sugerir algo, de repente, no hay nada.

Incluso los participantes que realmente ofrecen diferentes soluciones de software, no ofrecen un reemplazo para el CObject - más a menudo no lo utilizan en absoluto, menos a menudo utilizan su funcionalidad, sin prestar atención a la "implementación en un solo lugar", lo que significa que la implementación es bastante buena.

Si fuera malo, hace tiempo que habrían ofrecido un reemplazo.