Gracias por la respuesta, no eres nada malo) Ahora todo tiene sentido) UPD Esta construcción también funciona
Preste atención a lo que devuelve el método At(). Si devuelve NULL, se estrellará por un error crítico. Antes de acceder a un puntero a un objeto, comprueba que no es NULL
Ya lo he notado) Así que la solución es declarar objetos globalmente vacíos.... ¿Y si no se sabe de antemano cuántos serán? ¿Sólo declarar "con reserva"? :) P.D. No encontré esta forma de declarar objetos en la ayuda incorporada
Una vez Artyom me escribió esta clase. No puedo explicar en detalle cómo funciona. Pero Artem lo recordará y podrá explicarlo. Aquí está la clase en sí
#include <Arrays\ArrayObj.mqh>
/********************************************************************\
| Класс Новый бар |
\********************************************************************/class CNewBar : public CObject
{
private:
string m_symbol;
ENUM_TIMEFRAMES m_timeframe;
datetime m_time;
datetime Time(void); // Возвращает время нулевого бараstringSymbol(void) { returnthis.m_symbol; }
public:
ENUM_TIMEFRAMES Timeframe(void) { returnthis.m_timeframe; }
datetime GetTime(void) { returnthis.m_time; } // Возвращает время последнего обращенияbool IsNewBar(void); // Основная функция класса
CNewBar(conststring symbol,constENUM_TIMEFRAMES timeframe);
~CNewBar(void){;}
};
//+------------------------------------------------------------------+//| Конструктор |//+------------------------------------------------------------------+
CNewBar::CNewBar(conststring symbol,constENUM_TIMEFRAMES timeframe) : m_time(0)
{
this.m_symbol = symbol;
this.m_timeframe = (timeframe == PERIOD_CURRENT ? Period() : timeframe);
}
//+------------------------------------------------------------------+//| CNewBar Time Возвращает время нулевого бара |//+------------------------------------------------------------------+datetime CNewBar::Time(void)
{
datetime array[1], ret;
ret = CopyTime(this.m_symbol, this.m_timeframe, 0, 1, array) == 1 ? array[0] : 0;
return(array[0]);
}
//+------------------------------------------------------------------+//| CNewBar IsNewBar Основная функция класса |//+------------------------------------------------------------------+bool CNewBar::IsNewBar(void)
{
datetime tm = this.Time();
if(tm == 0)
returnfalse;
if(tm != this.m_time)
{
this.m_time = tm;
returntrue;
}
returnfalse;
}
Y aquí está el bucle de creación de punteros en OnInit()
for(int i = 0; i < ArraySize(Rates); i++)
{
CNewBar* nb = new CNewBar(Rates[i].m_Symbols, timefram);
if(nb != NULL)
{
list_new_bar.Add(nb);
Print(nb.IsNewBar(), " ***** ", Rates[i].m_Symbols, " ***** ", nb.Time());
}
}
y en OnTimer()
voidOnTimer()
{
int total = list_new_bar.Total();
for(int i = 0; i < ArraySize(Rates); i++)
{
CNewBar* nb = list_new_bar.At(i);
if(nb == NULL)
continue;
bool new_bar = nb.IsNewBar();
if(new_bar)
{// и дальше………
ArraySize(Rates) es el tamaño del array de estructuras en el que se encuentran los caracteres con los que se va a trabajar.
Artyom me escribió una vez esta clase. No puedo explicar en detalle cómo funciona. Pero Artyom lo recordará y podrá explicarlo. Aquí está la clase en sí
Y aquí está el bucle de creación de punteros en OnInit()
y en OnTimer()
ArraySize(Rates) es el tamaño del array de estructuras donde se listan los caracteres a trabajar.
Aquí:
for(int i = 0; i < ArraySize(Rates); i++)
Yo lo haría antes que el total - simplemente por la razón de que estás leyendo caracteres del array Rates (¿verdad?), creando instancias de la nueva clase de barra y añadiéndolas a la lista.
En cualquier error de adición, el tamaño de la lista de punteros a instancias de la nueva clase de barra no coincidirá con el tamaño del array Rates.
En general, debe ser algo así:
voidOnTimer()
{
int total = list_new_bar.Total();
for(int i = 0; i < total; i++)
{
CNewBar* nb = list_new_bar.At(i);
if(nb == NULL)
continue;
if(nb.IsNewBar())
{// и дальше………
Y aquí es donde también hay que comprobar si se ha añadido con éxito a la lista:
for(int i = 0; i < ArraySize(Rates); i++)
{
CNewBar* nb = new CNewBar(Rates[i].m_Symbols, timefram);
if(nb != NULL)
{
list_new_bar.Add(nb);
Print(nb.IsNewBar(), " ***** ", Rates[i].m_Symbols, " ***** ", nb.Time());
}
}
Yo lo haría antes que el total - simplemente por la razón de que se leen los caracteres del array Rates (¿no?), se crean instancias de la nueva clase bar y se añaden a la lista.
En cualquier error de adición, el tamaño de la lista de punteros a instancias de la nueva clase de barra no coincidirá con el tamaño del array Rates.
En general, debe ser algo así:
Y aquí es donde también hay que comprobar si se ha añadido con éxito a la lista:
algo así:
para evitar pérdidas de memoria cuando se añade por error un puntero a un nuevo objeto a la lista
Gracias. Lo tengo, lo corregiré de esta manera:)))
Odio continuar; operador y trato de no usarlo. Exclusivamente en casos desesperados.
if(nb==NULL)
continue;
en qué se diferencia de
if(nb!=NULL)
{
}
Otra cosa es que en caso de error se borre el puntero fallido... Pero incluso aquí podemos prescindir de hated continue; simplemente borrando Print(). Era necesario durante la depuración y tratar de entender lo que está pasando, y si durante el trabajo se produce algún error, no voy a entender lo que está mal de todos modos ... Es más fácil volver a instalar el sistema operativo que entender los registros.
Ya que estamos en el tema, dinos, sin entrar en detalles, cuál es la diferencia entre un puntero y una variable de clase, y cuál es preferible. Puedo leer sobre ello en Internet con detalles difíciles de entender. Me basta con una comprensión superficial, por así decirlo...
Preste atención a lo que devuelve el método At(). Si devuelve NULL, se estrellará por un error crítico. Antes de acceder a un puntero a un objeto, comprueba que no es NULL.
Artyom me escribió una vez esta clase. No puedo explicar en detalle cómo funciona. Pero Artyom lo recordará y podrá explicarlo. De todos modos, aquí está la clase en sí
//+------------------------------------------------------------------+//| CNewBar Time Возвращает время нулевого бара |//+------------------------------------------------------------------+datetime CNewBar::Time(void)
{
datetime array[1], ret;
ret = CopyTime(this.m_symbol, this.m_timeframe, 0, 1, array) == 1 ? array[0] : 0;
return(array[0]);
}
Alexey, gracias por una respuesta tan detallada. El propósito de la variable ret en el fragmento de código citado no está claro... ¿Para qué se calcula, si en algún caso el método devuelve array[0]? P.D. ¿Y por qué usar esto en un método de clase? Estamos trabajando con miembros de esta clase particular...
Odio el operador continue; e intento no usarlo. Exclusivamente en casos desesperados.
en qué se diferencia de
Otra cosa es que, cuando se produzca un error, se borre el puntero fallido... Pero aquí también se puede prescindir de hated continue; basta con borrar Print(). Era necesario durante la depuración y tratar de entender lo que está pasando, y si durante el trabajo se produce algún error, no voy a entender lo que está mal de todos modos ... Prefiero reinstalar el sistema operativo que entender los registros.
Ya que estamos en el tema, dinos, sin entrar en detalles, cuál es la diferencia entre un puntero y una variable de clase, y cuál es preferible. Puedo leer sobre ello en Internet con detalles difíciles de entender. A mí me basta con una comprensión superficial, por así decirlo.
Estoy tratando de deshacerme de los paréntesis innecesarios, para no hacer bosques y ramas. Sin la impresión no hay necesidad de paréntesis - sólo eliminar el objeto.
Con el nuevo operador se crea un mecanismo que se encuentra físicamente "en algún lugar". El nuevo operador devuelve la dirección de este "algún lugar". Y esa es la única forma de referirse a este "mecanismo".
Y el cerrojo dentro de ese mecanismo es una variable.
Alexey, gracias por una respuesta tan detallada. El propósito de la variable ret en el fragmento de código dado no está claro... ¿Por qué se calcula si el método devuelve array[0] de todos modos?
Alexey ha modificado algo en el código que le di. O tal vez yo también me lo perdí, lo escribí "de rodillas" como un simple ejemplo para explicar lo que ya no recuerdo.
Gracias por la respuesta, no eres nada malo)
Ahora todo tiene sentido)
UPD
Esta construcción también funciona
Preste atención a lo que devuelve el método At(). Si devuelve NULL, se estrellará por un error crítico. Antes de acceder a un puntero a un objeto, comprueba que no es NULL
Ya lo he notado)
Así que la solución es declarar objetos globalmente vacíos....
¿Y si no se sabe de antemano cuántos serán? ¿Sólo declarar "con reserva"? :)
P.D. No encontré esta forma de declarar objetos en la ayuda incorporada
Una vez Artyom me escribió esta clase. No puedo explicar en detalle cómo funciona. Pero Artem lo recordará y podrá explicarlo. Aquí está la clase en sí
Y aquí está el bucle de creación de punteros en OnInit()
y en OnTimer()
ArraySize(Rates) es el tamaño del array de estructuras en el que se encuentran los caracteres con los que se va a trabajar.
Artyom me escribió una vez esta clase. No puedo explicar en detalle cómo funciona. Pero Artyom lo recordará y podrá explicarlo. Aquí está la clase en sí
Y aquí está el bucle de creación de punteros en OnInit()
y en OnTimer()
ArraySize(Rates) es el tamaño del array de estructuras donde se listan los caracteres a trabajar.
Aquí:
Yo lo haría antes que el total - simplemente por la razón de que estás leyendo caracteres del array Rates (¿verdad?), creando instancias de la nueva clase de barra y añadiéndolas a la lista.
En cualquier error de adición, el tamaño de la lista de punteros a instancias de la nueva clase de barra no coincidirá con el tamaño del array Rates.
En general, debe ser algo así:
Y aquí es donde también hay que comprobar si se ha añadido con éxito a la lista:
algo así:
para evitar pérdidas de memoria cuando se añade por error un puntero a un nuevo objeto a la listaAquí:
Yo lo haría antes que el total - simplemente por la razón de que se leen los caracteres del array Rates (¿no?), se crean instancias de la nueva clase bar y se añaden a la lista.
En cualquier error de adición, el tamaño de la lista de punteros a instancias de la nueva clase de barra no coincidirá con el tamaño del array Rates.
En general, debe ser algo así:
Y aquí es donde también hay que comprobar si se ha añadido con éxito a la lista:
algo así:
para evitar pérdidas de memoria cuando se añade por error un puntero a un nuevo objeto a la listaGracias. Lo tengo, lo corregiré de esta manera:)))
Odio continuar; operador y trato de no usarlo. Exclusivamente en casos desesperados.
en qué se diferencia de
Otra cosa es que en caso de error se borre el puntero fallido... Pero incluso aquí podemos prescindir de hated continue; simplemente borrando Print(). Era necesario durante la depuración y tratar de entender lo que está pasando, y si durante el trabajo se produce algún error, no voy a entender lo que está mal de todos modos ... Es más fácil volver a instalar el sistema operativo que entender los registros.Ya que estamos en el tema, dinos, sin entrar en detalles, cuál es la diferencia entre un puntero y una variable de clase, y cuál es preferible. Puedo leer sobre ello en Internet con detalles difíciles de entender. Me basta con una comprensión superficial, por así decirlo...
Preste atención a lo que devuelve el método At(). Si devuelve NULL, se estrellará por un error crítico. Antes de acceder a un puntero a un objeto, comprueba que no es NULL.
Artem, gracias por el valioso comentario)
Gracias. Lo entiendo, lo arreglaré así... :)))
Odio el operador continue; e intento no usarlo. Exclusivamente en casos desesperados.
En qué se diferencia de
La iteración del bucle no terminará ni comenzará una nueva, sino que pasará a la siguiente iteración. La lógica cambiará.
Artyom me escribió una vez esta clase. No puedo explicar en detalle cómo funciona. Pero Artyom lo recordará y podrá explicarlo. De todos modos, aquí está la clase en sí
Alexey, gracias por una respuesta tan detallada.
El propósito de la variable ret en el fragmento de código citado no está claro...
¿Para qué se calcula, si en algún caso el método devuelve array[0]?
P.D.
¿Y por qué usar esto en un método de clase? Estamos trabajando con miembros de esta clase particular...
Gracias. Lo entiendo, lo arreglaré así... :)))
Odio el operador continue; e intento no usarlo. Exclusivamente en casos desesperados.
en qué se diferencia de
Otra cosa es que, cuando se produzca un error, se borre el puntero fallido... Pero aquí también se puede prescindir de hated continue; basta con borrar Print(). Era necesario durante la depuración y tratar de entender lo que está pasando, y si durante el trabajo se produce algún error, no voy a entender lo que está mal de todos modos ... Prefiero reinstalar el sistema operativo que entender los registros.Ya que estamos en el tema, dinos, sin entrar en detalles, cuál es la diferencia entre un puntero y una variable de clase, y cuál es preferible. Puedo leer sobre ello en Internet con detalles difíciles de entender. A mí me basta con una comprensión superficial, por así decirlo.
La iteración del ciclo no terminará y no comenzará una nueva, sino que pasará al siguiente Si. La lógica cambiará.
Alexey, gracias por una respuesta tan detallada.
El propósito de la variable ret en el fragmento de código dado no está claro...
¿Por qué se calcula si el método devuelve array[0] de todos modos?