OLP. Problèmes d'application - page 15

 

Le constructeur par défaut a un but spécifique pour initialiser un tableau d'objets de sa classe. Un constructeur dont tous les paramètres sont définis par défaut n' estpas un constructeur par défaut. Tut.

J'ai souligné un oubli en rouge.

Au fait, pourquoi un tel constructeur n'est-il pas un constructeur par défaut ? Une autre béquille ?

 
TheXpert:

Le constructeur par défaut a un but spécifique pour initialiser un tableau d'objets de sa classe. Un constructeur dont tous les paramètres sont définis par défaut n' estpas un constructeur par défaut. Ici

Une erreur de frappe intéressante, merci. Corrigé.
 
Yedelkin:

"Accès à un pointeur non valide" =="Tentative d'accès à un pointeur non valide" ?

C'est souvent le signe direct d'une mauvaise main ou d'un manque de compréhension des principes de base du travail avec les pointeurs.

Moins souvent un signe d'utilisation de classe mal documentée.

 
TheXpert:

Au fait, pourquoi ce constructeur n'est-il pas un constructeur par défaut ? Une autre béquille ?

C'est tout le contraire. La béquille consiste à avoir des paramètres par défaut, car c'est une source de bogues difficiles à trouver. C'est là que nous sommes stricts.

Si vous écrivez un constructeur avec des paramètres, vous pouvez également écrire un constructeur sans paramètre. Et si vous avez un constructeur par défaut, vous ne pouvez pas écrire un constructeur paramétrique avec tous les paramètres par défaut.

 
stringo:

C'est une béquille que d'avoir des paramètres par défaut, car c'est une source de bogues difficiles à attraper.

Oui, mais je ne peux pas penser à de telles situations.

Et s'il existe un constructeur par défaut, vous ne pouvez pas écrire un constructeur paramétrique avec tous les paramètres par défaut.

Ah, alors c'est normal et logique. Sinon, il y avait une sorte d'ambiguïté incompréhensible.
 

J'ai lu sur l'opération de résolution du contexte ( :: : ). J'ai décidé d'essayer de l'utiliser dans deux classes sans rapport :

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
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;
  }

Le compilateur donne une erreur sur la ligne C_A::funcA(j). Si je le commente, cela semble fonctionner. Quelle est mon erreur ?

 
Yedelkin:

J'ai lu sur l'opération de résolution du contexte ( :: : ). J'ai décidé d'essayer de l'utiliser dans deux classes sans rapport :

Le compilateur donne une erreur sur la ligne C_A::funcA(j). Si je le commente, cela semble fonctionner. Quelle est mon erreur ?

Dans votre cas, le contexte de la classe C_A n'est pas disponible pour la classe C_B.

C'est seulement correct si :

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
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);
     }
  };

Mais c'est possible :


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


En général, ces appels sont utilisés pour les méthodes surchargées:


//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
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;
  }

A peu près comme ça.

 
uncleVic:

Dans votre cas, le contexte de la classe C_A n'est pas disponible pour la classe C_B.

Merci. Je me suis donc trompé en disant que l'opération de résolution de contexte peut être appliquée sans héritage.
 

J'essaie de transmettre les valeurs des membres d'une classe à une autre "par référence" et en utilisant un descripteur. Les deux options semblent fonctionner. Voici le schéma le plus simple :

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();
  }

Laquelle de ces deux méthodes est la plus rapide ? Lequel est le plus préférable ?

 
Yedelkin:

J'essaie de transmettre les valeurs des membres d'une classe à une autre "par référence" et en utilisant un descripteur. Les deux variantes semblent fonctionner. Voici le schéma le plus simple :

Laquelle de ces deux méthodes est la plus rapide ? Lequel est le plus préférable ?

Les questions sont-elles vraiment lourdes/incorrectes ?

Pendant longtemps, j'ai utilisé la première méthode ("suivre le lien"), mais j'aime beaucoup l'idée des descripteurs. Je ne sais pas si ça vaut la peine de réécrire toutes les classes à cause de ça.