Preguntas sobre POO en MQL5 - página 45

 
Dmitry Fedoseev:

Puede alguien explicar cómo esta inicialización de los campos es mejor que esto:

es mejor que esto:

¿Y qué sentido tiene?

Los campos const pueden ser inicializados.

 
Dmitry Fedoseev:

Puede alguien explicar cómo esta inicialización de los campos es mejor que esto:

es mejor que esto:

¿Y qué sentido tiene?

En el primer caso se tiene la inicialización, y en el segundo caso - las operaciones se realizan para los campos inicializados por defecto. Así que todo depende del compilador, ya sea que no hace ninguna diferencia, o una mierda de acciones adicionales en tiempo de ejecución. En los pluses, la segunda variante se considera una mala forma.
 
El operador =, como debería, devuelve el valor r (5<(val=7) funciona), pero justo con la semántica de carry, aquí no hay, y se pidió, tristemente, así que tampoco hay constructor de carry.
 
Igor Makanu:

la cuestión es puramente teórica:

han visto, posiblemente en SB, una llamada al constructor como esta:

en qué se diferenciaría este código:

Lo he descomprimido, no veo ninguna diferencia, entonces sé un poco más específico - ¿qué o por qué podemos usar una llamada forzada al constructor para los objetos a1 y a2?

¿cuál es la "conveniencia" de la primera opción?

La primera opción se llama - Inicialización del valor, la segunda - Inicialización por defecto. Hay sutilezas y diferencias según el tipo de objeto (si es un agregado o con constructor por defecto, ...). Por ejemplo, el resultado aquí será absolutamente diferente si se utilizan paréntesis y sin ellos:

#include <iostream>
using namespace std;
struct S {
        int i;
        int q;
        int f;
};
struct Q : S {
        Q():S() {}
        //Q() {}
};
int main() {
        Q s;
        cout << s.i << s.q << s.f << endl;
}

Si quieres entender la teoría hasta las orejas, entra aquí https://en.cppreference.com/w/cpp/language/initialization

ZS: no todo es relevante para el mcl, sino para entender el modelo de referencia.

Initialization - cppreference.com
  • en.cppreference.com
Initialization of a variable provides its initial value at the time of construction. The initial value may be provided in the initializer section of a declarator or a new expression. It also takes place during function calls: function parameters and the function return values are also initialized. For each declarator, the initializer may be one...
 
Vict:

Si quieres ponerte hasta las orejas de la teoría, entra aquí https://en.cppreference.com/w/cpp/language/initialization

Todavía no es necesario, pero lo guardaré para saber dónde leer la fuente.

Gracias a todos.

Vladimir Simakov:
En los pluses, la segunda opción se considera una mala forma.

Habrá el mismo problema que encontré - duplicación de código para la inicialización de los campos, cuando sea necesario escribir más de un constructor en la clase

si usas la variante 2, puedes poner el código duplicado en un método separado y llamar a este método después de las acciones necesarias en cada constructor (tengo la inicialización de la clase por la estructura y la variante 2 por el nombre del archivo donde se escriben los datos de esta estructura (backup save))


Escribir ese código repetitivo es malo... no es interesante, pero el problema es que si añado un nuevo campo a la clase, tengo que recordar inicializar este campo tantas veces como constructores - el hecho, que no es conveniente, pero el hecho, que usted puede olvidarse de hacerlo N-veces, es un problema, imho

 
Igor Makanu:

Todavía no es necesario, pero lo guardaré, ya sabré dónde leer la fuente original.

Gracias a todos.

Habrá el mismo problema que encontré - duplicación de código para la inicialización de los campos, cuando sea necesario escribir más de un constructor en la clase

si usas la variante 2, puedes poner el código duplicado en un método separado y llamar a este método después de las acciones necesarias en cada constructor (tengo la inicialización de la clase por la estructura y la variante 2 por el nombre del archivo donde se escriben los datos de esta estructura (backup save))


Escribir ese código repetitivo es malo... no es interesante, pero el problema es que si añado un nuevo campo a la clase, tengo que recordar inicializar este campo tantas veces como constructores - el hecho, que no es conveniente, pero el hecho, que usted puede olvidarse de hacerlo N-veces, es un problema, imho

Una macro que también puede ser paramétrica. El olvido (yo mismo lo sufro), también se trata con este))))

 
Igor Makanu:

habrá el mismo problema que yo encontré - duplicación de código de inicialización de campos cuando hay necesidad de escribir más de un constructor en la clase

Si utiliza la variante 2, puede poner el código duplicado en un método separado y llamar a este método después de todas las acciones necesarias en cada constructor (tengo la inicialización de la clase por la estructura y la variante 2 por el nombre de un archivo donde se escriben los datos de esta estructura (copia de seguridad))


Escribir ese código repetitivo es malo... No es interesante, pero el problema es que si añado un nuevo campo a la clase, tendré que acordarme de inicializar este campo tantas veces como constructores haya - el hecho de que no sea conveniente, pero el hecho de que puedas olvidarte de hacerlo N veces, es un problema, imho

Vamos, que todo tiene solución:

class Q {
    void ctr_base(T t, S s) {//make init tasks
        }
public:
    Q(T t, S s, int i) {
        // make base init
        ctr_base(t, s);
        // make additional tasks
        ...
    }
    Q(T t, S s, strint str) {
        // make base init
        ctr_base(t, s);
        // make additional tasks
        ...
    }
};

No estoy en contra de los constructores por defecto (o de la inicialización por defecto), pero si tu constructor deja el objeto (bueno, si no es un agregado tonto) en un estado indefinido y luego lo inicializas mediante unas muletillas, entonces lo estás haciendo mal.

ZS: por cierto, se puede delegar el constructor en los pros, faltando por supuesto

class Foo {
public: 
  Foo(char x, int y) {}
  Foo(int y) : Foo('a', y) {} // Foo(int) delegates to Foo(char,int)
};
 
Vict:

Vamos, que tiene solución:

un poco por delante de mí, acaba de sentarse en el PC.

El consejo de @Vladimir Simakov de inicializar los campos de la clase usando una macro, para no olvidarse de inicializar correctamente, bueno, sí - buen truco, pero el código se leerá como una llamada a un método que inicializa los campos, difícil de asumir que este es un buen tono...


Tu ejemplo tampoco es el más refinado, pero resuelve el problema exactamente como lo hice yo ahora: un método de inicialización separado \N -.

imho, es una cuestión de propósito - la forma correcta de escribir una clase base con todos los campos necesarios, heredar de ella, hacer el constructor protegido e inicializar la clase base de los herederos y por lo tanto será la protección de "olvidar" - no hay constructor por defecto, ¿verdad? - al menos puedes mirar en mikrosoft si buscas en google "constructor protegido" - habrá un artículo


Mi problema es un poco diferente, dejé a propósito la herencia, para guardar el estado de los campos de la clase en un archivo, tengo 2 campos de 2 clases, y su estado también se guarda en el mismo archivo llamando a los métodos correspondientes. Intenté guardarlo todo cuando heredé de una clase base, se me hizo muy lioso, lo reescribí sin herencia, todo se volvió "transparente" ahora.

 
Igor Makanu:

Un poco por delante de mí, acaba de sentarse en el PC.

El consejo de @Vladimir Simakov de inicializar los campos de la clase usando una macro, para no olvidarse de inicializar correctamente, bueno, sí, es un buen truco, pero el código se leerá como si llamara a un método que inicializa los campos, difícil de asumir que es un buen tono...


Tu ejemplo tampoco es el más refinado, pero resuelve el problema exactamente como lo hice yo ahora: un método de inicialización separado \N -.

imho, es una cuestión de propósito - la forma correcta de escribir una clase base con todos los campos necesarios, heredar de ella, hacer el constructor protegido e inicializar la clase base de los herederos y por lo tanto será la protección de "olvidar" - no hay constructor por defecto, ¿verdad? - al menos puedes mirar en mikrosoft si buscas en google "constructor protegido" - habrá un artículo


Mi problema es un poco diferente, dejé a propósito la herencia, para guardar el estado de los campos de la clase en un archivo, tengo 2 campos de 2 clases y su estado también se guarda en el mismo archivo llamando a los métodos correspondientes. Intenté guardar todo cuando lo heredé de una clase base, se complicó mucho; lo rees cribí sin herencia, todo se volvió "transparente" ahora.

¿Qué tiene de confuso?

...
virtual void CBase::Save(int hndl){...}
...
CObj:public CBase
...
void CObj::Save(int hndl){
   CBase::Save(hndl);
   ...
}
 
Vladimir Simakov:

¿Qué tiene de confuso?

eso es exactamente lo que yo me alejé, y al principio lo hice

con este enfoque - heredar de una clase base, "donde está todo" - todo funciona, pero hasta que queremos intentar hacer varios campos de clase, y entonces queremos añadir varios campos en cada clase de campo y clavarlo todo con una matriz dinámica de clases

y entonces obtendremos que no podemos implementar el método Save(int hndl) propiamente dicho en una clase base - este método será en realidad una interfaz, que, como se ha comentado anteriormente, no será necesaria en absoluto - se puede escribir sin interfaces

Suelo maximizar mis esfuerzos en la flexibilidad del código - un mínimo de alboroto - el resultado es un nuevo problema resuelto, que mi terminología sea perdonada)))


el problema será que, al implementar el guardado en un archivo, es necesario elaborar el encabezado del archivo, que debe describir la cantidad total de los diferentes tipos de entradas y luego es necesario no perder la lógica / el orden de guardado de los datos, para poder leer todo correctamente.... y el final será si cambias aunque sea un campo de una clase

En mi opinión, la laboriosidad de una herencia tan "fácil" a partir de una clase base - se reduce al desarrollo y mantenimiento de una pequeña base de datos, a la supervisión constante de los cambios en cualquier clase

Razón de la queja: