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

 
Yedelkin:

Pergunta. Uma vez declarada uma função virtual com um conjunto específico de parâmetros e tipos numa classe pai, o número e os tipos de parâmetros das funções virtuais correspondentes podem ser alterados nas classes derivadas?

Por um lado, o Manual de Referência afirma que "uma função virtual pode ser substituída numa classe derivada ". A escolha da definição da função a chamar para a função virtual é feita de forma dinâmica (em tempo de execução). Um caso típico é quando uma classe base contém e as classes derivadas têm as suas próprias versões dessa função". Por outro lado, os exemplos dados no Manual de Referência referem-se a casos em que as funções virtuais têm corpos de definição de funções diferentes em vez de cabeçalhos de definição de funções.

Tanto quanto me consigo lembrar, é possível. Mas é preciso ser absolutamente cuidadoso quanto aos tipos e número de parâmetros.

Também é necessário ter cuidado com os tipos de valores passados e os valores por defeito.

Aqui estão alguns exemplos de simplicidade.

Esta variante vai fazer o truque.

boll MyFunction(int Param);
boll MyFunction(int Param1,int Param2);

Este não funciona (ou melhor, talvez funcione, mas com alguns bugs e certas reservas).

//Ели второй параметр будет упущен, то компилятор может и не "понять" смысла всего задуманного
boll MyFunction(int Param);
boll MyFunction(int Param1,int Param2 = 0);
//Так тоже может не прокатить по причине совпадения типов у второго параметра
boll MyFunction(int Param1,color Param2);
boll MyFunction(int Param1,int Param2);

Acontece exactamente a mesma coisa quando se recarregam métodos dentro de uma classe.

 
mql5:
Apenas uma cópia exacta da definição, excepto para as definições por defeito (os valores por defeito podem variar, mas é melhor não os utilizar)
Quer dizer "apenas uma cópia exacta do cabeçalho da definição"? Afinal de contas, a definição da função inclui o cabeçalho mais o corpo. Os corpos nos exemplos são definitivamente diferentes.
 

Interessante, tal como eu o entendo, a virtualização da função e sobrecarga da função são coisas ligeiramente diferentes. Eo mql5 diz que na virtualização de funções deve haver uma cópia impressa do cabeçalho da função (não levo em conta os parâmetros por defeito).

 
Yedelkin:

Interessante, tal como o entendo, a virtualização da função e a sobrecarga da função são coisas um pouco diferentes. Eo mql5 diz que na virtualização de funções deve haver uma cópia impressa do cabeçalho da função (não estou a ter em conta os parâmetros por defeito).

> Pergunta. Após declaração de uma função virtual com um determinado conjunto de parâmetros e os seus tipos numa classe pai, é possível alterar o número e os tipos de parâmetros das funções virtuais correspondentes nas classes descendentes?

Se bem entendi, a criança deve sobrecarregar a funcionalidade do antepassado.

Francamente falando, não me lembro de fazer tais coisas com o virtual (penso que sim), mas a afirmação sobre sobrecarga é verdadeira - eu próprio cometi esse erro uma vez.

PS

Se tudo for feito correctamente, como eu entendo, o número de parâmetros pode ser tanto aumentado como diminuído. As dificuldades serão se o número de parâmetros permanecer o mesmo, mas os seus tipos forem alterados...

 

Seja como for, esbocei este exemplo:

class C_A             //родительский класс
{
 public:
 virtual double function(double a1, double a2, double a3) { return; }
}
class C_B : public C_A
{
 public:
 virtual double function(double a1, double a2, double a3) { return(a1);   }
}
class C_C : public C_A
{
 public:      
 virtual double function(double a1, double a2, double a3) { return(a2);   }
        double function(double a1, double a2)           { return(a1+a2); }
}
//где-то в программе объявляем указатель
C_A  *pointer;
int random=rand()%2;
   switch(random)
     {
      case 0: pointer=new C_B; break;
      case 1: pointer=new C_C; break;
     }

//вызываем виртуальный метод
   if(pointer!=NULL)
     {
      pointer.function(a1,a2,a3);
     }

Acontece que independentemente de um método de função estar ou não sobrecarregado na classe C_C, uma função virtual pode ser chamada com apenas três parâmetros - pointer.function(a1,a2,a3). De forma correspondente, o programa nunca chegará ao método dos dois parâmetros da classe C_C quando chamar as funções virtuais. Certo?

 
Yedelkin:

Seja como for, esbocei este exemplo:

Acontece que independentemente de um método de função estar ou não sobrecarregado na classe C_C, uma função virtual pode ser chamada com apenas três parâmetros - pointer.function(a1,a2,a3). De forma correspondente, o programa nunca chegará ao método dos dois parâmetros da classe C_C quando chamar as funções virtuais. Certo?

Analisar o que o programa faz inserindo nos construtores e destruidores impressões com __FUNÇÃO__ macro, será muito útil.

Também acrescentaria que, declarando um ponteiro a uma classe base, constrói-se assim um "túnel" para os descendentes através da classe base. Assim, o compilador verá apenas funções declaradas na classe base em classes descendentes. Se você (mesmo dentro do mesmo programa) declarar directamente um objecto descendente, todas as funções estarão disponíveis no mesmo.

class C_A             //родительский класс
{
 public:
 virtual double function(double a1, double a2, double a3) { return; }
}
class C_B : public C_A
{
 public:
 virtual double function(double a1, double a2, double a3) { return(a1);   }
}
class C_C : public C_A
{
 public:      
 virtual double function(double a1, double a2, double a3) { return(a2);   }
        double function(double a1, double a2)           { return(a1+a2); }
}
//где-то в программе объявляем указатель
C_A  *pointer;
int random=rand()%2;
   switch(random)
     {
      case 0: pointer=new C_B; break;
      case 1: pointer=new C_C; break;
//вызываем виртуальный метод
   if(pointer!=NULL)
     {
      pointer.function(a1,a2,a3);
     }
C_С  *new_pointer=new C_C;
      new_pointer.function(a1,a2);
 
Yedelkin:

Seja como for, esbocei este exemplo:

Acontece que independentemente de um método de função estar ou não sobrecarregado na classe C_C, uma função virtual pode ser chamada com apenas três parâmetros - pointer.function(a1,a2,a3). De forma correspondente, o programa nunca chegará ao método dos dois parâmetros da classe C_C quando chamar as funções virtuais. Certo?

Pela minha própria experiência, posso recomendar-lhe que embale o código da seguinte forma

double function(double a1, double a2)            {return(a1+a2);}
double function(double a1, double a2, double a3) {return(a2);}

E pode ver o ficheiro anexo como um exemplo e entretenimento.

Não queria incomodar-me com indicações e novidades, por isso declarei simplesmente a classe trabalhadora como uma variável.

O Expert Advisor gera um número aleatório 0/1 em intervalos iguais e, dependendo do resultado, desempenha uma de duas funções: MarketBuy / MarketSell.


Pode fazê-lo desta forma se quiser

bool MarketBuy(string SymbolTitle,double LotSize,double TP = 0.0,double SL = 0.0);
bool MarketSell(string SymbolTitle,double LotSize,double TP = 0.0,double SL = 0.0);

Mas, neste caso, pode ocorrer um erro devido ao conflito com

bool MarketBuy(string SymbolTitle,double LotSize);
bool MarketSell(string SymbolTitle,double LotSize);


PS

Fi-lo à mão, e por isso pode haver algumas imprecisões.

Mas, em princípio, a ideia básica pode ser compreendida.

Arquivos anexados:
Forum.mq5  18 kb
 

Muito obrigado pelos valiosos conselhos e orientação! Irei certamente usá-los, mas gostaria de ter tempo suficiente tanto para a teoria como para a prática.

Interesting:

A partir da minha própria experiência, posso recomendar que se complete o código

double function(double a1, double a2)            {return(a1+a2);}
double function(double a1, double a2, double a3) {return(a2);}
Porquê fazê-lo desta forma? O que é a armadilha?
 
Yedelkin:

Porque é que é assim? O que é a armadilha?

Costumava haver um problema com isso, penso eu. Mas não me consigo lembrar quais são agora.

De qualquer modo, habituei-me a isso.

Normalmente não há diferença, claro, pelo menos no meu exemplo tentei trocar de lugar e tudo funcionou...

 
Interesting:

Costumava haver um problema com isso, penso eu. Mas não me consigo lembrar quais são agora.

OK, em qualquer caso - vou ter isso em mente.
Razão: