OLP. Problemi di applicazione - pagina 15

 

Il costruttore di default ha uno scopo specifico per inizializzare un array di oggetti della sua classe. Un costruttore con tutti i suoi parametri impostati su default non è un costruttore di default. Tut.

Ho evidenziato una svista in rosso.

A proposito, perché un tale costruttore non è un costruttore di default? Un'altra stampella?

 
TheXpert:

Un costruttore di default ha uno scopo specifico per inizializzare un array di oggetti della sua classe. Un costruttore con tutti i suoi parametri impostati su default non è un costruttore di default. Qui

Interessante refuso, grazie. Corretto.
 
Yedelkin:

"Invalid pointer access" =="Attempting to access an invalid pointer"?

Spesso un segno diretto di una cattiva mano o della mancanza di comprensione dei principi di base del lavoro con i puntatori.

Meno spesso un segno di un uso della classe mal documentato.

 
TheXpert:

A proposito, perché questo costruttore non è un costruttore di default? Un'altra stampella?

Al contrario. La stampella è avere parametri predefiniti, poiché questo è una fonte di bug difficili da trovare. È qui che siamo severi.

Se scrivete un costruttore con parametri, siete in grado di scrivere anche un costruttore senza parametri. E se avete un costruttore di default, non potete scrivere un costruttore parametrico con tutti i parametri di default.

 
stringo:

È una stampella per avere parametri predefiniti, poiché questo è una fonte di bug difficili da catturare.

Sì, in qualche modo non mi viene in mente nessuna situazione del genere.

E se c'è un costruttore di default, non puoi scrivere un costruttore parametrico con tutti i parametri di default.

Ah, allora è normale e logico. Altrimenti c'era una sorta di ambiguità incomprensibile.
 

Ho letto dell'operazione di risoluzione del contesto ( ::: ). Ho deciso di provare ad usarlo in due classi non collegate:

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
class C_B;
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
class C_A
  {
public:
   C_B              *pointer;

                     C_A(void) {};
                    ~C_A(void) {};
   void funcA(int i) { Print("funcA(",i,")=",i); }
  };
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
class C_B
  {
public:
                     C_B(void) {};
                    ~C_B(void) {};
   void funcB(int j)
     {
      Print("funcB(",j,")=",j);
      C_A::funcA(j);
     }
  };
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void OnStart()
  {
   C_A object;
   object.pointer=new C_B();
   object.pointer.funcB(5);
   delete object.pointer;
  }

Il compilatore dà un errore sulla linea C_A::funcA(j). Se lo commento, sembra funzionare. Qual è il mio errore?

 
Yedelkin:

Ho letto dell'operazione di risoluzione del contesto ( ::: ). Ho deciso di provare ad usarlo in due classi non collegate:

Il compilatore genera un errore sulla linea C_A::funcA(j). Se lo commento, sembra funzionare. Qual è il mio errore?

Nel vostro caso, il contesto della classe C_A non è disponibile dalla classe C_B.

È corretto solo se:

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
class C_B : public C_A
  {
public:
                     C_B(void) {};
                    ~C_B(void) {};
   void funcB(int j)
     {
      Print("funcB(",j,")=",j);
      C_A::funcA(j);
     }
  };

Ma poi può:


//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
class C_B : public C_A
  {
public:
                     C_B(void) {};
                    ~C_B(void) {};
   void funcB(int j)
     {
      Print("funcB(",j,")=",j);
      funcA(j);
     }
  };


In generale, tali chiamate sono utilizzate per i metodi sovraccaricati:


//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
class C_B;
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
class C_A
  {
public:
   C_B              *pointer;

                     C_A(void) {};
                    ~C_A(void) {};
   void func(int i) { Print("C_A::func(",i,")=",i); }
  };
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
class C_B : public C_A
  {
public:
                     C_B(void) {};
                    ~C_B(void) {};
   void func(int j)
     {
      Print("C_B::func(",j,")=",j);
      C_A::func(j);
     }
  };
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void OnStart()
  {
   C_A object;
   object.pointer=new C_B();
   object.pointer.func(5);
   delete object.pointer;
  }

All'incirca così.

 
uncleVic:

Nel vostro caso, il contesto della classe C_A non è disponibile dalla classe C_B.

Grazie. Quindi mi sbagliavo sul fatto che l'operazione di risoluzione del contesto può essere applicata senza ereditarietà.
 

Sto cercando di passare i valori dei membri da una classe all'altra "per riferimento" e usando un descrittore. Entrambe le opzioni sembrano funzionare. Ecco lo schema più semplice:

class B
  {
private:
   double            d1;
public:
                     B(double &d) {  d1=d; Print("class B, double d1=",d1);  };
                    ~B(void){};
  };
class A
  {
public:
   double            double_var;
   A                *pointerA;
 

                     A(void) : double_var(1.234567),pointerA(NULL) { SetPointer(); };
                    ~A(void) {if(CheckPointer(pointerA)==POINTER_DYNAMIC) delete pointerA; };
private:
   void SetPointer(void) { pointerA=GetPointer(this); }
  };
class C 
  {
public:
   A                *pointerA_C;
public:
                     C(void) : pointerA_C(NULL) {};
                    ~C(void) {if(CheckPointer(pointerA_C)==POINTER_DYNAMIC) delete pointerA_C;};
   void Printer() {if(CheckPointer(pointerA_C)!=POINTER_INVALID) Print("class C, double =",pointerA_C.double_var); };
  };
void OnStart()
  {
   A objA;
//---передаём значение double-переменной по ссылке
   B objB(objA.double_var);
//---передаём значение double-переменной через описатель
   C objC;
   objC.pointerA_C=objA.pointerA;
   objC.Printer();
  }

Quale di questi due metodi funziona più velocemente? Cosa è più preferibile?

 
Yedelkin:

Sto cercando di passare i valori dei membri da una classe all'altra "per riferimento" e usando un descrittore. Entrambe le opzioni sembrano funzionare. Ecco lo schema più semplice:

Quale di questi due metodi funziona più velocemente? Cosa è più preferibile?

Le domande sono davvero pesanti/corrette?

Per molto tempo ho usato il primo modo ("seguire il link"), ma mi piace molto l'idea dei descrittori. Solo che non so se vale la pena riscrivere tutte le classi a causa di questo.

Motivazione: