Perguntas OOP (Object Oriented Programming) - página 6

 
C-4:
Os apontadores são indispensáveis para conversões de objetos complexos onde a identificação dinâmica do tipo é necessária.

Vasily, um exemplo, por favor!

Só conheço um caso em que você precisa alocar memória e precisa de um ponteiro para isso.

Tenho certeza de que quase sempre se pode passar sem ele. É desejável não utilizar o gerenciamento manual de memória. Há sempre uma biblioteca padrão que já trata destas questões.

 
Integer:


Um princípio se aplica em todos os lugares: tudo deve ser feito da maneira mais simples possível. Você não precisa entrar na espessura das coisas só para estar na espessura das coisas. Se um problema pode ser resolvido de forma simples, ele deve ser resolvido de forma simples.


Exatamente. E é aqui que é importante projetar a classe corretamente. E para fazer isso, é importante prever quais serão as próximas classes (descendentes).

Normalmente, a classe base deve ter uma funcionalidade mínima, mas é desejável criar muitos métodos virtuais que definiriam o vetor de uso da classe.

No caso da MQL - provavelmente o contrário - mais funcionalidade na classe base, como na VOLDEMAR. Mas sem fanatismo.


Existem propriedades de símbolos comerciais (POINT, STOPLEVEL etc.). MODE_XXX para MarketInfo() ). É melhor empurrá-los para a classe cSymbol, por exemplo.


Existem propriedades do pedido (preço de abertura, tipo, lote, etc.). OrderXXX() ). Seria melhor colocá-los em uma classe de ordem separada, por exemplo.

Se lembrarmos que o pedido pode ser fechado em partes, então devemos também atribuir o campo BaseLot à classe (para saber qual parte do lote já foi fechada), etc.


Há (para mim) um cronograma - períodos de tempo especificados (por dia) em que podemos abrir e fechar pedidos, períodos em que só fecharemos (trilhando se já tivermos atingido o ponto de equilíbrio) e o período em que não trabalharemos de forma alguma e, em seguida, fecharemos todos os pedidos abertos e apagamos os não abertos.

Lembre-se das lacunas e que na última hora de negociação em muitas (se não todas) corretoras podem mudar as condições de negociação e que muitas corretoras têm uma quebra na negociação de metais a cada dia de negociação.


E finalmente, há um EA - um certo algoritmo que funciona com um certo símbolo, em um determinado horário, com uma certa lista de "suas" ordens e com seus próprios dados para o cálculo.

Podemos criar uma classe cExpert, que conterá um objeto da classe cSymbol e um conjunto de objetos da classe cOrder. Este cExpert básico conterá funções de atualização das propriedades dos objetos de ordem, funções de manipulação de pedidos, manipulação de erros, estatísticas, etc.

Pessoalmente considero úteis as funções de cálculo de lote em %% do AccountFreeMargin(), geração de assistente único para cada ordem (mais fácil de colocar uma ordem inversa para uma ordem específica), função de colocar uma ordem inversa, etc.

E é daqui que o cExpert poderia descer com conjuntos únicos de dados e funções adicionais que decidiriam o que fazer no mercado (abrir/empresa/fechar ordens).

Isto é, implementar estratégias comerciais. E será o que chamamos de "XXX estratégia EA".


Mas TODAS as funcionalidades da base estarão na classe cExpert base. As classes infantis conterão algoritmos de estratégias comerciais.

Bem, talvez alguém acrescente algum tratamento avançado de erros ou estatísticas avançadas sobre comércio (se não houver código fonte e este não puder ser amontoado no cExpert básico).

Por favor, note que estamos levando nosso tempo e criando uma aula que simplificará a escrita de EAs. Na verdade, trata-se de um modelo de Expert Advisor. Estruturalmente completo e sem escovas (todos os dados necessários em um só lugar com o código).


Quanto à suposta "redundância" das funções de invólucro sobre as ordens abertas(), eu pessoalmente apenas apóio tais invólucros (especialmente - se eles tiverem funções adicionais, não apenas uma chamada para uma função básica).

Por exemplo, se em uma chamada de invólucro SL e TP são especificados em pontos e temos que convertê-los em dígitos absolutos, e além disso adicionar ou subtrair dependendo do tipo de ordem (embora neste caso também tais conversões podem ser colocadas em operorders()).

Pessoalmente, acho mais fácil entender o código chamando BuyStop(...) e verificar uma vez que BuyStop() faz tudo corretamente do que analisar os parâmetros OrderSend() para a exatidão dos parâmetros a cada vez.

PS: Foi muito trabalho, inclusive nos fins de semana. Graças ao Pavlick e ao mql5 para os códigos de exemplo.

Dê uma olhada nesses exemplos e pense: é realmente necessário criar uma hierarquia de classes na área de tarefas de programação, que estão escritas em MQL?

Você realmente precisa de uma família inteira de classes baseada em uma básica (todos aqueles "triângulos", "quadrados", etc.)?

E mais uma vez as palavras de ouro da Integer: Não vá para a mata só para estar na mata.

Oh. Ou eu não notei, ou a seção de documentação com exemplos apareceu recentemente.

 
Zhunko:

Só conheço um caso em que você precisa alocar memória e precisa de um ponteiro para isso.

Tenho certeza de que quase sempre se pode passar sem ele. É aconselhável não utilizar o gerenciamento manual de memória. Há sempre uma biblioteca padrão que já resolveu estes problemas.


Provavelmente é disto que se trata.


Vamos assumir que existe uma classe cFather, ela tem o método GetData() que retorna 3. E o método PrintData(), que produz o que recebe de GetData().

Há seu descendente cChild que anulou GetData() que agora retorna 5.

Se declararmos um objeto do tipo cFather TestObject, então TestObject.GetData() sempre retornará 3.

Se declararmos cFather* TestObject=new cChild1, então TestObject.GetData() retornará 5, mesmo que pareça ser cFather.

É necessário para que o código escrito agora possa chamar o método GetData() em qualquer descendente da classe cFather, mesmo que ele (classe descendente) ainda não exista.

Isto é, se a classe cChild2 aparecer, com a qual GetData() retornará 7, então após cFather* Test2=nova função cChild2 Test2.PrintData() começará a sair 7.

Se há alguma função que espera um parâmetro "referência ao objeto da classe cFather" e o utiliza GetData(), ele obterá dados corretos para qualquer descendente do cFather.

A vinculação do método ocorre quando é chamado novo. Se não for referenciada, então a ligação será difícil, ou seja, os métodos da classe declarada serão chamados.

Veja aqui e aqui

 
EverAlex:

Isto parece ser o que está em jogo.

...

Há um operador "::" que permite acessar qualquer método em toda a cadeia de classes base e derivadas sem alocar memória ou um ponteiro.
 
C-4:


Sua classe é 90% redundante. Apenas duas funções fazem o trabalho principal, são as ordens abertas e dica Por que você usa Sel, Buy SelStop, etc., quando na verdade todas elas simplesmente chamam Openorders? Além disso, o tipo de pedido é passado como int, portanto, não é protegido. Em vez de int é melhor usar ou sua própria enumeração ou o ENUM_ORDER_TYPE padrão. E em geral, é melhor nunca usar números mágicos "1", "2" etc., apenas enumerações. Isto impedirá que você envie o valor da ordem à esquerda para a função. A própria função Openorders é muito grande. Obviamente, ele consiste em dois blocos, o bloco de fazer um negócio e o bloco de verificar as condições. Cada uma delas deve ser uma função privada separada.

Isso é um bom começo, mas ainda temos muito a aprender. A função da ponta seria melhor reescrita da seguinte forma:

É conveniente para mim ver visualmente que tipo de pedido estou fazendo quando chamo o método.

Sobre a comparação, descreva em detalhes porque não é recomendado comparar o dobro com 0 ?

 
C-4:
Os apontadores são indispensáveis para conversões de objetos complexos onde a identificação dinâmica do tipo é necessária.

A presença de identificação de tipo dinâmico geralmente indica a arquitetura de muleta de um projeto.
 
se uma classe for declarada globalmente em uma EA (Classe c;) os estados dos objetos de classe interna mudados em um tick serão salvos quando o tick seguinte chegar ?
 
EverAlex:

Parece ser disso que se trata.


Suponha, existe a classe cFather; ela tem o método int GetData() que retorna 3. E o método PrintData(), que produz o que recebe de GetData().

Há seu descendente cChild, que anulou GetData(), que agora retorna 5.

Se declararmos um objeto do tipo cFather TestObject, então TestObject.GetData() sempre retornará 3.

Se declararmos cFather* TestObject=new cChild1, então TestObject.GetData() retornará 5, mesmo que pareça ser cFather.

É necessário para que o código escrito agora possa chamar o método GetData() em qualquer descendente da classe cFather, mesmo que ele (classe descendente) ainda não exista.

Isto é, se a classe cChild2 aparecer, com a qual GetData() retornará 7, então após cFather* Test2=nova função cChild2 Test2.PrintData() começará a sair 7.

Se há alguma função que espera um parâmetro "referência ao objeto da classe cFather" e o utiliza GetData(), ele obterá dados corretos para qualquer descendente do cFather.

A vinculação do método ocorre quando é chamado novo. Se não for referenciada, então a ligação será difícil, ou seja, os métodos da classe declarada serão chamados.

Veja aqui e aqui

class cFather
{
public:
    int GetData() {return 3;}
};

class cChild : public cFather
{
public:
    int GetData() {return 5;}
};
    
int f(cFather *p) {return p->GetData();}
    
int main()
{
    cChild obj;
    f(&obj);                // вернет 3
    obj.cFather::GetData(); // вернет 3
    
    return 0;
}
 
Pavlick:


Talvez eu tenha escrito o exemplo para nada. Não funciona em MKL:

cChild obj;
f(&obj);                // вернет 3
obj.cFather::GetData(); // вернет 3

H.k., não são indicadores, mas risos em um bastão.

P.S: escreva em dlls, há uma chance de aprender um idioma normal.

 
Pavlick:


Talvez eu tenha escrito o exemplo para nada. Não funciona em MKL:

H.k., não são indicadores, mas risos em um bastão.

P.S: escreva em dlls, há uma chance de aprender um idioma normal.


class cFather
  {
public:
   int GetData() {return 3;}
  };
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
class cChild : public cFather
  {
public:
   int GetData() {return 5;}
  };

int f(cFather *p) {return p.GetData();}
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
int OnStart()
  {
   cChild obj,*ptr=GetPointer(obj);
   f(ptr);                     // вернет 3
   ((cFather *)ptr).GetData(); // вернет 3

   return 0;
  }