OLP. Questões de aplicação - página 15

 

Um construtor com todos os seus parâmetros definidos como padrão não é um computador padrão. Tut.

Destaquei um lapso a vermelho.

A propósito, porque é que um construtor deste tipo não é um construtor por defeito? Outra muleta?

 
TheXpert:

Um construtor por defeito tem um objectivo específico de inicialização de um conjunto de objectos da sua classe. Um construtor com todos os seus parâmetros definidos por defeito não é um computador por defeito. Aqui

Gratidão pela gralha interessante. Corrigido.
 
Yedelkin:

"Invalid pointer access" =="Tentativa de acesso a um ponteiro inválido"?

Muitas vezes um sinal directo de uma mão má ou falta de compreensão dos princípios básicos de trabalhar com apontadores.

Menos frequentemente um sinal de uso de classe mal documentado.

 
TheXpert:

A propósito, porque é que este construtor não é um construtor por defeito? Outra muleta?

Muito pelo contrário. A muleta está a ter parâmetros padrão, uma vez que é uma fonte de bugs difíceis de encontrar. É aqui que estamos a ser rigorosos.

Se escrever um construtor com parâmetros, também é capaz de escrever um construtor sem parâmetros. E se tiver um construtor padrão, não pode escrever um construtor paramétrico com todos os parâmetros padrão.

 
stringo:

É uma muleta ter parâmetros por defeito, pois esta é uma fonte de bugs difíceis de apanhar.

Sim, de alguma forma não consigo pensar em nenhuma dessas situações.

E se houver um construtor padrão, não se pode escrever um construtor paramétrico com todos os parâmetros padrão.

Ah, então é normal e lógico. Caso contrário, havia algum tipo de ambiguidade incompreensível.
 

Li sobrea operação de resolução de contexto ( :::: ). Decidi tentar utilizá-lo em duas classes não relacionadas:

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

O compilador dá um erro na linha C_A::funcA(j). Se eu o comentar, parece funcionar. Qual é o meu erro?

 
Yedelkin:

Li sobrea operação de resolução de contexto ( :::: ). Decidi tentar utilizá-lo em duas classes não relacionadas:

O compilador gera um erro na linha C_A::funcA(j). Se eu o comentar, parece funcionar. Qual é o meu erro?

No seu caso, o contexto da classe C_A não está disponível a partir da classe C_B.

Só é correcto 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);
     }
  };

Mas depois pode:


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


Em geral, tais chamadas são utilizadas para métodos sobrecarregados:


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

Aproximadamente assim.

 
uncleVic:

No seu caso, o contexto da classe C_A não está disponível a partir da classe C_B.

Obrigado. Por isso, estava errado que a operação de resolução de contexto possa ser aplicada sem herança.
 

Estou a tentar passar os valores dos membros de uma classe para outra "por referência" e utilizando um descritor. Ambas as opções parecem funcionar. Aqui está o esquema mais simples:

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

Qual destes dois métodos funciona mais rapidamente? O que é mais preferível?

 
Yedelkin:

Estou a tentar passar os valores dos membros de uma classe para outra "por referência" e utilizando um descritor. Ambas as variantes parecem funcionar. Aqui está o esquema mais simples:

Qual destes dois métodos funciona mais rapidamente? O que é mais preferível?

As perguntas são realmente pesadas/incorretas?

Durante muito tempo utilizei a primeira via ("seguindo a ligação"), mas gosto muito da ideia dos descritores. Só não sei se vale a pena reescrever todas as aulas por causa disso.