Preguntas de POO (Programación Orientada a Objetos) - página 6

 
C-4:
Los punteros son indispensables para las conversiones complejas de objetos en las que se necesita una identificación dinámica del tipo.

Vasily, un ejemplo, por favor.

Sólo conozco un caso en el que hay que asignar memoria y se necesita un puntero a la misma.

Estoy seguro de que casi siempre se puede prescindir de él. Es conveniente no utilizar la gestión manual de la memoria. Siempre hay una biblioteca estándar que ya se encarga de estas cuestiones.

 
Integer:


Hay un principio que se aplica en todas partes: todo debe hacerse de la forma más sencilla posible. No hay que meterse en el meollo de la cuestión sólo para estar en el meollo de la cuestión. Si un problema puede resolverse de forma sencilla, debe resolverse de forma sencilla.


Exactamente. Y aquí es donde es importante diseñar la clase correctamente. Y para ello, es importante predecir cuáles serán las siguientes clases (descendientes).

Por lo general, la clase base debe tener una funcionalidad mínima, pero es deseable crear una gran cantidad de métodos virtuales que establezcan el vector de uso de la clase.

En el caso de MQL - probablemente lo contrario - más funcionalidad en la clase base, como en VOLDEMAR. Pero sin fanatismo.


Existen propiedades de símbolos comerciales (PUNTO, NIVEL DE PARADA, etc.). MODE_XXX para MarketInfo() ). Será mejor que los metamos en la clase cSymbol, por ejemplo.


Hay propiedades de las órdenes (precio de apertura, tipo, lote, etc.). OrderXXX() ). Sería mejor ponerlos en una clase cOrder separada, por ejemplo.

Si recordamos que el pedido puede cerrarse por partes, entonces debemos asignar también el campo BaseLot a la clase (para saber qué parte del lote ya se ha cerrado), etc.


Hay (para mí) un horario - periodos de tiempo especificados (por día) cuando podemos abrir y cerrar órdenes, periodos en los que sólo cerramos (trailing si ya hemos alcanzado el punto de equilibrio) y el periodo en el que no trabajamos en absoluto y entonces cerramos todas las órdenes abiertas y borramos las no abiertas.

Recuerde sobre las brechas y que en la última hora de negociación en muchas (si no todas) las empresas de corretaje pueden cambiar las condiciones de negociación y que muchas empresas de corretaje tienen un descanso en los metales de negociación cada día de negociación.


Y finalmente, hay un EA - un cierto algoritmo que trabaja con un cierto símbolo, en un cierto horario, con una cierta lista de "sus" órdenes y con sus propios datos para calcular.

Podemos crear una clase cExpert, que contendrá un objeto de la clase cSymbol y un array de objetos de la clase cOrder. Este cExpert básico contendrá funciones de actualización de las propiedades de los objetos cOrder, funciones de gestión de pedidos, gestión de errores, estadísticas, etc.

Personalmente encuentro útiles las funciones de cálculo de lotes en %% de AccountFreeMargin(), generación de asistente único para cada orden (más fácil de poner una orden inversa a una orden específica), función de colocar una orden inversa, etc.

Y aquí es donde cExpert podría descender, con conjuntos únicos de datos y funciones adicionales que decidirían qué hacer en el mercado (órdenes de apertura/compañía/cierre).

Es decir, aplicar estrategias de negociación. Y será lo que llamamos un "EA de estrategia XXX".


Pero TODA la funcionalidad base estará en la clase base cExpert. Las clases hijas contendrán algoritmos de estrategias de negociación.

Bueno, tal vez alguien añada algún manejo avanzado de errores o estadísticas avanzadas sobre el comercio (si no hay código fuente y no se puede embutir en el cExpert básico).

Tenga en cuenta que nos estamos tomando nuestro tiempo y creando una clase que simplificará la escritura de EAs. De hecho, es una plantilla de Asesor Experto. Estructuralmente completo y sin cepillar (todos los datos necesarios en un solo lugar con el código).


En cuanto a la supuesta "redundancia" de las funciones de envoltura sobre openorders(), yo personalmente sólo apoyo tales envolturas (especialmente - si tienen funcionalidad extra, y no sólo llaman a la función básica).

Por ejemplo, si en una llamada de wrapper SL y TP se especifican en puntos y tenemos que convertirlos a dígitos absolutos, y además sumar o restar dependiendo del tipo de orden (aunque en este caso también se pueden colocar dichas conversiones en operorders()).

Personalmente me parece más fácil entender el código que llama a BuyStop(...) y comprobar una vez que BuyStop() lo hace todo correctamente que analizar los parámetros de OrderSend() para ver si son correctos cada vez.

PD: Era mucho trabajo, incluso los fines de semana. Gracias a Pavlick y mql5 por los códigos de ejemplo.

Echa un vistazo a estos ejemplos y piensa, ¿es realmente necesario crear una jerarquía de clases en el ámbito de las tareas de programación, que están escritas en MQL?

¿Realmente se necesita toda una familia de clases basadas en una básica (todos esos "triángulos", "cuadrados", etc.)?

Y una vez más las palabras de oro de Integer: No te metas en la espesura sólo por estar en la espesura.

O no me he dado cuenta, o la sección de documentación con ejemplos ha aparecido recientemente.

 
Zhunko:

Sólo conozco un caso en el que hay que asignar memoria y se necesita un puntero a la misma.

Estoy seguro de que casi siempre se puede prescindir de él. Es aconsejable no utilizar la gestión manual de la memoria. Siempre hay una biblioteca estándar que ya ha resuelto estos problemas.


Probablemente se trata de esto.


Supongamos que hay una clase cFather, que tiene el método int GetData() que devuelve 3. Y el método PrintData(), que emite lo que obtiene de GetData().

Hay su descendiente cChild que ha anulado GetData() que ahora devuelve 5.

Si declaramos un objeto de tipo cFather TestObject, entonces TestObject.GetData() siempre devolverá 3.

Si declaramos cPadre* TestObject=new cChild1, entonces TestObject.GetData() devolverá 5, aunque parezca ser cPadre.

Es necesario para que el código escrito ahora pueda llamar al método GetData() en cualquier descendiente de la clase cFather, incluso si ésta (la clase descendiente) no existe todavía.

Es decir, si entonces aparece la clase cChild2, con la que GetData() devolverá 7, entonces después de la función cFather* Test2=new cChild2 Test2.PrintData() empezará a emitir 7.

Si hay alguna función que espera un parámetro "referencia al objeto de clase cFather" y la utiliza GetData(), obtendrá datos correctos para cualquier descendiente de cFather.

La vinculación del método se produce cuando se llama a new. Si no está referenciada, la vinculación será dura, es decir, se llamará a los métodos de la clase declarada.

Véase aquí y aquí

 
EverAlex:

Parece que de esto se trata.

...

Existe un operador "::" que permite acceder a cualquier método de toda la cadena de clases base y derivadas sin asignar memoria o un puntero.
 
C-4:


Su clase es redundante en un 90%. Sólo dos funciones hacen el trabajo principal, éstas son openorders y tip ¿Por qué se utiliza Sel, Buy SelStop, etc., cuando en realidad todas ellas sólo llaman a Openorders? Además, el tipo de orden se pasa como int, por lo que no está protegido. En lugar de int, es mejor utilizar su propia enumeración o el estándar ENUM_ORDER_TYPE. Y, en general, es mejor no utilizar nunca los números mágicos "1", "2", etc., sólo las enumeraciones. Esto evitará que envíe el valor de la orden izquierda a la función. La propia función de Openorders es demasiado grande. Obviamente, consta de dos bloques, el bloque de hacer un trato y el bloque de comprobar las condiciones. Cada una de ellas debe ser una función privada independiente.

Es un buen comienzo, pero aún nos queda mucho por aprender. La función de la punta se reescribiría mejor de la siguiente manera:

Es conveniente para mí ver visualmente qué tipo de orden estoy haciendo cuando llamo al método...

Sobre la comparación, describa detalladamente por qué no es recomendable comparar el doble con el 0 ?

 
C-4:
Los punteros son indispensables para las conversiones complejas de objetos en las que se necesita una identificación dinámica del tipo.

La presencia de la identificación de tipos dinámicos suele indicar la arquitectura de muletas de un proyecto.
 
si una clase se declara globalmente en un EA (Clase c;) ¿se guardarán los estados de los objetos internos de la clase cambiados en un tick cuando llegue el siguiente?
 
EverAlex:

Parece que se trata de esto.


Supongamos que existe la clase cFather; tiene el método int GetData() que devuelve 3. Y el método PrintData(), que emite lo que obtiene de GetData().

Está su descendiente cChild, que ha anulado GetData(), que ahora devuelve 5.

Si declaramos un objeto de tipo cFather TestObject, entonces TestObject.GetData() siempre devolverá 3.

Si declaramos cPadre* TestObject=new cChild1, entonces TestObject.GetData() devolverá 5, aunque parezca ser cPadre.

Es necesario para que el código escrito ahora pueda llamar al método GetData() en cualquier descendiente de la clase cFather, incluso si ésta (la clase descendiente) no existe todavía.

Es decir, si entonces aparece la clase cChild2, con la que GetData() devolverá 7, entonces después de la función cFather* Test2=new cChild2 Test2.PrintData() empezará a emitir 7.

Si hay alguna función que espera un parámetro "referencia al objeto de clase cFather" y la utiliza GetData(), obtendrá datos correctos para cualquier descendiente de cFather.

La vinculación del método se produce cuando se llama a new. Si no está referenciada, la vinculación será dura, es decir, se llamará a los métodos de la clase declarada.

Véase aquí y aquí

class cFather
{
public:
    int GetData() {return 3;}
};

class cChild : public cFather
{
public:
    int GetData() {return 5;}
};
    
int f(cFather *p) {return p->GetData();}
    
int main()
{
    cChild obj;
    f(&obj);                // вернет 3
    obj.cFather::GetData(); // вернет 3
    
    return 0;
}
 
Pavlick:


Quizás escribí el ejemplo para nada. No funciona en MKL:

cChild obj;
f(&obj);                // вернет 3
obj.cFather::GetData(); // вернет 3

H.k., no punteros, sino risas en un palo.

P.D: escribe en dlls, hay una oportunidad de aprender un lenguaje normal.

 
Pavlick:


Tal vez escribí el ejemplo para nada. No funciona en MKL:

H.k., no punteros, sino risas en un palo.

P.D: escribe en dlls, hay una oportunidad de aprender un lenguaje normal.


class cFather
  {
public:
   int GetData() {return 3;}
  };
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
class cChild : public cFather
  {
public:
   int GetData() {return 5;}
  };

int f(cFather *p) {return p.GetData();}
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
int OnStart()
  {
   cChild obj,*ptr=GetPointer(obj);
   f(ptr);                     // вернет 3
   ((cFather *)ptr).GetData(); // вернет 3

   return 0;
  }
Razón de la queja: