
Do básico ao intermediário: Sobrecarga
Introdução
O conteúdo exposto aqui, visa e tem como objetivo, pura e simplesmente a didática. De modo algum deve ser encarado como uma aplicação final, onde o objetivo não seja o estudo dos conceitos aqui mostrados.
No artigo anterior Do básico ao intermediário: Ponto Flutuante, falamos o básico do básico sobre ponto flutuante. Como aquele material é ao meu ver algo importante de ser devidamente compreendido. O apresentei neste começo de caminhada. Isto por que, entender como os tipos float e double funcionam é algo imprescindível para conseguir entender outras questões futura.
Apesar de aquele conteúdo, ser apenas o básico do que realmente precisa ser, verdadeiramente muito bem assimilado, por quem deseja se tornar um bom programador. Ele já será suficiente para que possamos falar de outras coisas. Apesar de tudo, muito provavelmente em um momento oportuno iremos precisar voltar a falar mais sobre ponto flutuante. Mas com um conteúdo um pouco mais avançado. Mas isto é algo para ser pensado em um momento futuro.
No entanto, aquele artigo, ao meu ver, já irá ajudar muitos a entender, que o fato de estarmos mexendo com um programa. Ou melhor dizendo, uma plataforma de negociação. Onde errar significa perder dinheiro. Não podemos tentar ser totalmente exatos em nossas convicções. Isto por que o próprio ponto flutuante, nos impede de sermos totalmente exatos e precisos. Tudo que podemos fazer e tentar sermos o mais próximo, quanto for possível de um valor que consideramos adequado ou justificável. Isto para poder efetuar uma compra ou venda de um dado ativo, ou produto financeiro.
Bem, mas estas questões tem muito mais a ver com operadores ou usuários de uma plataforma, do que com nossa atividade principal. Que no caso é a programação. Nós como programadores, devemos alertar aos usuários de nossas aplicações que existe sim um risco embutido nos cálculos. Porém, depende do usuário ou operador, ajustar e analisar se os dados reportados de fato fazem sentido para ele. Efetuar uma compra ou venda em um dado momento.
Entretanto, ainda não vejo que estamos com uma base suficientemente construída e sólida o bastante, para que possamos começar a falar em como programar, ou implementar um indicador, ou um Expert Advisor, vulgo robô. Apesar de já termos uma boa noção do que é necessário e pode ser feito. Ao meu entender, podemos acabar ficando meio que com as mãos atadas em certos momentos. Isto por que, existem coisas que ainda não foram explicadas. E as mesmas de fato, são necessárias em diversos momentos e para diferentes propósitos. Muitas das vezes nos permitindo fazer coisas que, sem o devido conhecimento, não seria possível de serem feitas.
E como não quero, em artigos futuros, ficar explicando certos detalhes, que podem ser chatos e cansativos. Quero montar uma base completa e perfeitamente sólida para de fato apresentar materiais mais avançados. Isto tornará tanto os artigos mais interessantes, como também ajudará trazer um conteúdo de melhor qualidade. Já que não necessitando explicar certos detalhes, posso focar em passar ainda mais conhecimento nos artigos futuros.
Ainda falta explicar algumas coisas, que para muitos iniciantes pode ser bastante complicado. Porém, é algo que de fato precisa ser explicado antes de progredimos para um próximo nível.
Assim como foi feito, com relação a Arrays e Strings, onde mostrei que uma coisa leva a outra. Também existe a necessidade de explicar um outro recurso antes de falarmos de um recurso um pouco mais avançado. Isto pelo simples motivo, que fará muito mais sentido, entender como um dado recurso, aparentemente confuso, nos permite gerar um que muitos iniciantes não utilizam, por não o entender. Sendo forçados a criar uma serie de rotinas, funções e procedimentos, que muitas vezes são completamente desnecessários em um código mais elaborado. Ou melhor dizendo, um código feito por um programador, com um conhecimento melhor sobre como criar algo usando esta ou aquela linguagem. No nosso caso MQL5.
Então para separar as coisas de maneira adequada, vamos a um novo tópico.
Entendendo o que seria uma sobrecarga
Se é algo que faz muito programador iniciante, ou mesmo um programador ocasional, ficar completamente perdido e sem entender absolutamente nada de um código. É quando dentro de um mesmo código, temos duas funções ou procedimentos com um mesmo nome. Sim, este tipo de coisa acontece, e quando ocorre deixa muito programador menos experiente, ou com menos conhecimento completamente perdido. Não conseguindo corrigir, melhorar ou mesmo criar um código com base em outro.
Este tipo de coisa, apesar de ser para olhos leigos, algo extremamente confuso e sem nenhuma lógica. É totalmente possível, permitido e aceito pelo compilador. Desde que você siga certas regras simples.
Como sei, e entendo que muitos, deve estar dizendo que sou louco, ou perdi completamente a noção do que posso estar falando. Visto que muitos não fazem ideia de como usar duas chamadas com objetivos levemente diferentes, mas que contém o mesmo nome. Vamos ver um exemplo bem simples. Mas muito simples mesmo, apenas para demonstrar isto que estou querendo dizer e irei explicar.
Agora vamos olhar para o código logo abaixo.
01. //+------------------------------------------------------------------+ 02. #property copyright "Daniel Jose" 03. //+------------------------------------------------------------------+ 04. void OnStart(void) 05. { 06. Print(Sum(10, 25)); 07. Print(Sum(-10, 25.)); 08. } 09. //+------------------------------------------------------------------+ 10. ulong Sum(ulong arg1, ulong arg2) 11. { 12. Print(__FUNCTION__, "::", __LINE__); 13. return arg1 + arg2; 14. } 15. //+------------------------------------------------------------------+ 16. double Sum(double arg1, double arg2) 17. { 18. Print(__FUNCTION__, "::", __LINE__); 19. return arg1 + arg2; 20. } 21. //+------------------------------------------------------------------+
Código 01
E então, meu caro leitor, quero que você olhe para este código 01 e responda com toda a sinceridade. Antes de ver o resultado da execução. Como este código irá de fato funcionar? Ou para deixar mais claro. Você já deve saber que quando usamos o a chamada Print, em um código. Queremos imprimir um valor qualquer no terminal do MetaTrader 5. E aqui temos quatro chamadas ao procedimento de biblioteca Print.
Então, reformulando a mesma pergunta que foi feita anteriormente: Você, consegue me dizer o que será impresso no terminal? Obviamente você pode olhar para as linhas seis e sete e dizer: Bem, será impresso o valor de 35 e o valor de 15. Mas isto é a parte obvia do negócio. A parte que me interessa é saber qual das duas funções serão executadas. A função Sum da linha dez ou a função Sum da linha dezesseis? Hum, deixe-me ver. Epá. Mas isto não irá compilar, já que temos duas funções com o mesmo nome. Tanto na linha dez quanto na linha dezesseis. Você achou que iria me pegar nesta?
Bem, meu caro leitor, de fato, e você não deixa de estar totalmente certo, isto seria realmente uma pegadinha. Já que duas funções ou procedimentos NÃO PODEM TER O MESMO NOME. Isto é fato, e quem disser o contrário estará mentindo ou no mínimo escondendo alguma coisa. Porém, todavia e, entretanto, isto não se aplica aqui. Por mais estranho que possa parecer. Estas duas funções Sum, presentes nas linhas dez e dezesseis NÃO SÃO A MESMA COISA. Mesmo que ambas fazem o mesmo trabalho e executem isto da forma correta. Elas não são vistas pelo compilador como sendo uma, mas como duas funções distintas. Mesmo que elas tenham o mesmo nome.
Certo, agora fiquei confuso de fato. Pois para mim, duas funções ou procedimentos não poderiam ter o mesmo nome. Isto quando formos utilizá-las em um mesmo código. Isto é verdade, não podem. Mas aqui estamos fazendo o que é conhecido como sobrecarga de funções ou procedimentos.
Esta questão da sobrecarga é um dos temas que mais me gera alegria de programar. Isto porque, se bem planejada a sobrecarga nos permite implementar códigos muito mais legíveis. Se bem que existe formas melhores de se fazer isto. Porém, sem entender a sobrecarga, que você está vendo neste código 01. É praticamente, isto para não dizer impossível, entender um outro recurso presente na linguagem MQL5. Mas vamos deixar isto para outro momento. Primeiro, vamos entender o que seria e como funciona a sobrecarga.
A sobrecarga é exatamente isto que você está vendo nas linhas dez e dezesseis deste código 01. Quando você o executar, ele irá gerar o que é visto na imagem logo abaixo.
Imagem 01
O que nos interessa aqui, não é o valor que será impresso pelas linhas seis e sete. Mas sim estes valores que estão sendo destacados na imagem. Estes são os dados que de fato nos interessa aqui, e neste momento. Note que em um caso, estamos nos referindo a linha 12 e em outro a linha 18. Por que? O motivo é o tipo de valor empregado nas chamadas das linhas seis e sete. Quando o compilador estiver tentando gerar o executável, ele irá olhar para estes valores e dizer: Bem, este valor combina com este parâmetro esperado por esta função. Aquele valor combina com aquele outro parâmetro. E assim ele vai conseguindo resolver as chamadas, de forma que podemos ter chamadas com um mesmo nome. Porém, e é esta a parte importante. Os argumentos, ou parâmetros esperados NÃO PODEM SER IGUAIS. Até podem ter uma certa semelhança. Porém eles devem ser diferentes em número, ou um deles ser de tipo diferente. Caso contrário, o compilador não conseguirá entender, para onde o código deverá ser dirigido, e isto é considerado um erro.
Observe que neste caso, tanto Sum presente na linha dez, quanto o da linha dezesseis, tem tipos diferentes sendo utilizados. Como o segundo argumento da linha sete é diferente do tipo inteiro, o compilador sabe que neste caso deverá chamar a função onde um tipo ponto flutuante é esperado naquele argumento.
Para fixar este conhecimento. Vamos ver um outro caso.
01. //+------------------------------------------------------------------+ 02. #property copyright "Daniel Jose" 03. //+------------------------------------------------------------------+ 04. void OnStart(void) 05. { 06. Print(Sum(10, 25)); 07. Print(Sum((char)-10, 25)); 08. } 09. //+------------------------------------------------------------------+ 10. ulong Sum(int arg1, ulong arg2) 11. { 12. Print(__FUNCTION__, "::", __LINE__); 13. return arg1 + arg2; 14. } 15. //+------------------------------------------------------------------+ 16. double Sum(char arg1, ulong arg2) 17. { 18. Print(__FUNCTION__, "::", __LINE__); 19. return (double)(arg1 + arg2); 20. } 21. //+------------------------------------------------------------------+
Código 02
Agora preste atenção, pois este código 02, tem o mesmo resultado que é visto na imagem 01. Porém aqui já não estamos lidando com algo tão simples como antes. Sendo este um tipo de código que muitos programadores menos experientes consideram confuso demais. E tentam modificar o mesmo, a fim de corrigir a aparente confusão que está sendo gerada. No entanto ao fazer isto acabam criando um problema para si. Já que o resultado não é o mesmo esperado. Ou conseguido pelo criador do código. Por conta disto, antes de você tentar modificar um código desconhecido meu caro leitor. Procure estudar como o mesmo funciona. Se possível, execute ele de maneira controlada. Isto a fim de conseguir entender o fluxo de execução. Pois pode ser que algo esteja lhe escapando, e tentar mudar algo, antes mesmo de o entender. É um dos maiores erros que um iniciante pode cometer.
Agora vamos entender o seguinte: A função Sum, presente nas linhas dez e dezesseis, deste código 02, continua retornando o mesmo tipo de valor. Veja que estamos fazendo uso de uma conversão explicita na linha 19. Isto para que o compilador não venha a reclamar de que estamos usando tipos diferentes.
Mas o detalhe agora é o seguinte: Note que a diferença entre a função Sum, da linha dez e da linha dezesseis é o tipo do primeiro argumento a ser recebido por ela. Este tipo de coisa costuma dar um nó no cérebro de muita gente. Isto por que, à primeira vista não faz sentido termos um tipo de 4 bytes para a função da linha dez e termos um tipo de 1 byte para a função da linha dezesseis.
De fato, neste exemplo que estamos utilizando, isto é completamente desnecessário. Porém, pode ser que o programador por qualquer motivo, venha a trabalhar internamente nas funções de modo que, a função da linha dezesseis, de fato precise receber um tipo char. Já que o tipo int pode não ser adequado. Lembrando que existe forma de resolver isto de uma outra maneira.
No entanto, isto será visto em outro artigo. Aqui estamos considerando que você não saiba como fazer tal coisa. Então decide fazer como está sendo mostrado no código 02.
Pergunta: Isto está errado? Não, meu caro leitor, criar, escrever e implementar um código, como é visto no código 02, não está errado. Apenas demonstra que você ainda tem e precisa aprender um pouco mais sobre como programar em MQL5. Mas definitivamente não está errado.
Bem, estas foram as formas simples de sobrecarga. Existe um outra, onde ao invés de declarar parâmetros de tipos diferentes. Usamos um número diferente de parâmetros. Este caso, talvez possa ser o mais comum. Visto que diferente do C e C++, onde podemos implementar um número praticamente infinito de parâmetros. Sem mudar a declaração da função ou procedimento. Aqui no MQL5, não podemos fazer isto. Bem isto em teste. pois existe uma forma de se fazer isto. Mostrei como, em um artigo anterior. Se bem que aquilo foi apenas um aperitivo para o que realmente podemos fazer, quando certos recursos tiverem sido explicados.
Mas novamente vamos considerar que você, meu caro leitor, esteja de fato aprendendo e queira aprender da maneira correta. Então como seria esta outra forma de sobrecarga? Bem, ela pode ser vista logo abaixo.
01. //+------------------------------------------------------------------+ 02. #property copyright "Daniel Jose" 03. //+------------------------------------------------------------------+ 04. void OnStart(void) 05. { 06. Print(Sum(10, 25)); 07. Print(Sum(-10, 25, 4)); 08. } 09. //+------------------------------------------------------------------+ 10. long Sum(long arg1, long arg2) 11. { 12. Print(__FUNCTION__, "::", __LINE__); 13. return arg1 + arg2; 14. } 15. //+------------------------------------------------------------------+ 16. long Sum(long arg1, long arg2, long arg3) 17. { 18. Print(__FUNCTION__, "::", __LINE__); 19. return arg1 + arg2 + arg3; 20. } 21. //+------------------------------------------------------------------+
Código 03
Bem neste caso o resultado seria o que você pode observar na imagem logo na sequência.
Imagem 02
Até onde já consegui observar, grande parte dos iniciantes tem mais facilidade em entender este tipo de código 03 do que os demais. Visto que parece mais simples de entender qual seria a função ou procedimento que seria de fato chamado em cada caso. Muitos não consideram este tipo de implementação, vista no código 03, como um tipo de sobrecarga. Porém na literatura, muitos autores de fato consideram isto um tipo de sobrecarga. Já que o nome da função continua sendo o mesmo.
Ok, acredito que tenha dado para entender o que seria ou não uma sobrecarga. Porém uma pergunta ainda reside. Por que ela funciona e como o compilador consegue distinguir entre uma e outra, apenas pelo fato de estamos utilizando tipos diferentes? Isto aparentemente não faz muito sentido. Não à primeira vista.
De fato, meu caro leitor, isto não faz muito sentido. Visto que quando utilizamos uma função usamos o nome que a mesma foi declarada. E não algo diferente disto. Mas então por que funciona? O motivo, é que para um código realmente poder se tornar executável. É preciso que o compilador consiga entender como direcionar adequadamente o fluxo de execução. E quando a sobrecarga, neste caso de funções e procedimentos. É utilizada, o compilador irá criar um nome, interno, único. Digo interno, pois você não sabe exatamente como isto será feito. Apesar de que, em geral isto é feito, fazendo uso de algumas regras simples.
Por exemplo: Olhando para o código 03, na linha dez, o compilador pode chamar aquela função Sum de Sum_long_long, já a função da linha dezesseis, ele pode chamar ela de Sum_long_long_long. Observe que apesar de aparentemente simples, isto já faz muita diferença. Pois seria como se estivéssemos criando uma função com um nome único.
A mesma coisa se aplica ao código 02. Ali a função da linha dez, pode estar sendo chamada de Sum_int_ulong, já a da linha dezesseis de Sum_char_ulong. Note que agora a coisa começa a fazer mais sentido. E daí o fato de que o compilador, consiga entender para onde o fluxo de execução deveria ser direcionado em um dado momento.
Uma observação importante: Aqui estou usando esta nomenclatura apenas por motivos didáticos. Já que dependendo da implementação e forma como os desenvolvedores do compilador pensaram. Esta nomenclatura pode ser totalmente diferente. Mas entenda que, internamente o compilador irá fazer algo parecido com isto.
Perfeito, estamos praticamente terminando o que seria o uso de sobrecarga. Falta apenas mais dois exemplos que ao meu ver pode ser interessante de serem mostrados. O primeiro é visto logo abaixo.
01. //+------------------------------------------------------------------+ 02. #property copyright "Daniel Jose" 03. //+------------------------------------------------------------------+ 04. void OnStart(void) 05. { 06. int v = -5; 07. 08. Sum(v, Sum(10, 25)); 09. Print(v); 10. } 11. //+------------------------------------------------------------------+ 12. long Sum(long arg1, long arg2) 13. { 14. Print(__FUNCTION__, "::", __LINE__); 15. return arg1 + arg2; 16. } 17. //+------------------------------------------------------------------+ 18. void Sum(int &arg1, long arg2) 19. { 20. Print(__FUNCTION__, "::", __LINE__); 21. 22. arg1 += (int)arg2; 23. } 24. //+------------------------------------------------------------------+
Código 04
Neste caso temos a possibilidade de usar uma função sendo sobrecarregada, junto com um procedimento. Note que os nomes são iguais. Porém devido a questão de tipos podemos ter o fluxo sendo desviado em um ou outra direção. é importante notar que dependendo da maneira como este código 04 tenha sido implementado. Isto quando nos referimos aos tipos de argumentos utilizados, assim como a forma de estruturar o código. Ele pode apresentar um ou outro resultado. Isto pelo simples fato de termos modificado algum mínimo detalhe nas declarações. Tanto de tipo, quanto na forma como a linha oito está sendo pensada.
Pois observe o seguinte fato. Apesar da linha oito aparamente está se referindo a função presente na linha 12. O fato de estarmos utilizando uma variável no primeiro argumento, faz com que tenhamos a intenção de chamar a linha 18. Porém, se o tipo declarado na linha oito não for compatível com o tipo esperado na linha 18, poderemos de fato nunca chamar a linha 18. Sendo tudo feito dentro da linha 12. Por conta disto, é aconselhável não utilizar a sobrecarga de funções e procedimentos de maneira indevida ou sem um cuidado adequado. Visto que podemos ter resultados bem conflitantes com os esperados inicialmente.
No entanto, da forma como o código 04 se encontra, ao executarmos o mesmo, iremos visualizar o resultado que pode ser visto na imagem na sequência.
Imagem 03
Novamente, este tipo de resposta, somente ocorreu por conta que os tipos combinaram perfeitamente bem. E o compilador conseguiu compreender qual seria a nossa intenção. No entanto, se algum programador, antes de estudar e entender o código, vier a decidir que não queira usar tipos long em seu código, já que ele é de 64 bits, e decide usar apenas tipo int, por ser de 32 bits, veja o que ocorrerá. Quanto tais mudanças forem feitas. O mesmo código 04, foi modificado, como descrito, e se tornou o código 05 que pode ser visto na sequência.
01. //+------------------------------------------------------------------+ 02. #property copyright "Daniel Jose" 03. //+------------------------------------------------------------------+ 04. void OnStart(void) 05. { 06. int v = -5; 07. 08. Sum(v, Sum(10, 25)); 09. Print(v); 10. } 11. //+------------------------------------------------------------------+ 12. int Sum(int arg1, int arg2) 13. { 14. Print(__FUNCTION__, "::", __LINE__); 15. return arg1 + arg2; 16. } 17. //+------------------------------------------------------------------+ 18. void Sum(int &arg1, int arg2) 19. { 20. Print(__FUNCTION__, "::", __LINE__); 21. 22. arg1 += (int)arg2; 23. } 24. //+------------------------------------------------------------------+
Código 05
Observe que foi feita uma mudança muito inocente e sem muita pretensão de causar problema. Mas ao tentar criar o executável, eis que o compilador diz não entender o que está sendo implementado. Já que a mensagem vista na saída do compilador é mostrada logo abaixo.
Imagem 04
Ou seja, uma tentativa totalmente inocente de mudar o código para algo que o programador achava mais adequado, acabou tornando o código totalmente incompreendido. Já que o compilador não sabe se deve ir para a linha 12 ou para a linha 18, quando a linha oito tiver que ser executada. Porém, quero que você, meu caro leitor, entenda uma coisa aqui. O erro NÃO ESTÁ NA LINHA OITO. O erro na verdade está no fato de que temos duas chamadas, que ao entender do compilador são exatamente iguais. O programador por ter pouca experiência, vai logo imaginar que o problema está na linha oito. Quando na verdade ele está ou na linha 12 ou na linha 18, como foi explicado anteriormente. Já que o compilador, pode estar criando um nome interno único para tentar criar o executável final.
Neste tipo de abordagem, que aqui parece ser simples de ser resolvida. Pode ser extremamente complicada na prática. Isto por que, uma chamada pode estar em um arquivo de cabeçalho. Enquanto a outra pode estar em outro arquivo de cabeçalho que pode não ter absolutamente nada a ver com o primeiro. O que torna a coisa ainda mais complicada e confusa.
E como último exemplo, vamos ver um outro caso, onde a sobrecarga está sendo utilizada. Este é visto no código mostrado logo abaixo.
01. //+------------------------------------------------------------------+ 02. #property copyright "Daniel Jose" 03. //+------------------------------------------------------------------+ 04. void OnStart(void) 05. { 06. long v = -16, 07. m[]; 08. bool b; 09. 10. Add(m, Sum(10, 25)); 11. Print("Return: ", b = Sum(v, m)); 12. if (b) Print("Value: ", v); 13. ArrayFree(m); 14. } 15. //+------------------------------------------------------------------+ 16. void Add(long &arg[], long value) 17. { 18. ArrayResize(arg, arg.Size() + 1); 19. arg[arg.Size() - 1] = value; 20. } 21. //+------------------------------------------------------------------+ 22. long Sum(long arg1, long arg2) 23. { 24. Print(__FUNCTION__, "::", __LINE__); 25. return arg1 + arg2; 26. } 27. //+------------------------------------------------------------------+ 28. bool Sum(long &arg1, const long &arg2[]) 29. { 30. Print(__FUNCTION__, "::", __LINE__); 31. 32. if (arg2.Size() == 0) 33. return false; 34. 35. for (uchar c = 0; c < arg2.Size(); c++) 36. arg1 += arg2[c]; 37. 38. return true; 39. } 40. //+------------------------------------------------------------------+
Código 06
Este daqui é de fato um caso muito interessante, e que tem muitas implicações práticas. Isto por que, não é raro, pelo menos aqui no MQL5, cujo objetivo é criar mecanismos para gerar interpretação gráfica de preços e negócios. Implementarmos um código cujo propósito, ou objetivo principal, seja o de efetuar algum tipo de fatoração com múltiplos dados de cotação. Normalmente este tipo de fatoração está de alguma forma atrelada ao desenvolvimento de algum indicador específico ou algum modelo de negociação a ser utilizado em um Expert Advisor. Isto a fim de gerar alguma indicação gráfica plausível. E chamar a atenção do operador ou usuário da plataforma MetaTrader 5, para abrir ou fechar alguma posição. Ou no mínimo ficar atento a alguma movimentação específica que pode ocorrer em alguns instantes.
Sei que muitos, principalmente iniciantes, ficam afoitos para criar algo e ver isto sendo executado. Porém, antes mesmo de podermos fazer isto, é preciso entender justamente este tipo de coisa, que estamos vendo nestes artigos de agora. Onde o material é mais básico e visa justamente criar uma base sólida para podemos trabalhar depois. Com algo mais elaborado e voltado a algum tipo de atividade específica. Como não quero ficar perdendo muito tempo, explicando detalhes simples futuramente. Estou criando esta base de conhecimento agora. Assim, você, meu caro leitor, poderá adaptar ou mesmo melhorar o que será visto nos artigos com material mais específico. Não somente os meus. Mas de qualquer outro programador, que você queira usar parte da ideia ou do código apresentado.
Pois bem, neste código 06, temos exatamente um exemplo de sobrecarga, onde hora utilizaremos um valor discreto, de maneira bem interessante. Hora iremos utilizar um conjunto de valores, que estarão presentes em um array de dados. Porém, apesar desta aparente simplicidade, não é raro, termos problemas nos cálculos que estão sendo efetuados. Isto por conta de pequenas falhas no entendimento de certos conceitos básicos. Entre estas falhas, está o fato, de que muitas das vezes, acabamos cometendo o pecado, de não nos atentar aos valores iniciais de parâmetros repassados a uma função. Este tipo de coisa, costuma dar um certo trabalho para ser corrigido. Isto até que venhamos a perceber o motivo da falha.
Mas este tipo de coisa é mais fácil de ser compreendida na prática. E conforme você for pegando experiência, vai sendo cada vez mais difícil de cometer tal erro. Se bem que quando ele vier a ocorrer será devido a alguma distração que você teve durante a implementação.
Mas vamos entender o que temos aqui no código 06. Quando executamos este código como mostrado acima. Você terá o seguinte resultado mostrado logo abaixo.
Imagem 05
Agora entenda o seguinte meu caro leitor. Como foi dito a pouco, não é raro termos problemas em fatorações múltiplas. Isto por conta de estarmos usando, um número errado de elementos na fatoração. Para evitar isto, abrimos mão de retornamos o valor na função, e passamos a retornar uma indicação. Esta irá nos dizer se o valor fatorado, deverá ou não ser aceito. Então na linha 32 testamos este tipo de coisa. Note que a função Sum, ainda assim está sendo sobrecarregada. Já que na linha 22 temos o mesmo nome que é dado a função da linha 28. Porém, o fato de o valor retornado não ter o mesmo objetivo, não implica que a função não esteja sendo sobrecarregada.
Este tipo de coisa pode muitas vezes ser confuso. Ainda mais quando olhamos apenas as linhas onde a função está sendo utilizada. Observe isto, ao olhar as linhas dez e onze. Você claramente nota que não faz muito sentido o que estamos retornando ali. Por isto, sempre que tiver dúvidas a respeito de como um código funciona, procure estudar os detalhes do mesmo. Não imagine que só por uma função ou procedimento ter o mesmo nome de uma outra função ou procedimento, que você já conhece. Ambas irão fazer e trabalhar da mesma maneira. Pois nem sempre é assim que as coisas funcionam.
E para terminar, podemos fazer uma pequena mudança no código 06. Esta é mostrada no fragmento logo abaixo.
01. //+------------------------------------------------------------------+ 02. #property copyright "Daniel Jose" 03. //+------------------------------------------------------------------+ 04. void OnStart(void) 05. { 06. long v = -16, 07. m[]; 08. bool b; 09. 10. // Add(m, Sum(10, 25)); 11. Print("Return: ", b = Sum(v, m)); 12. if (b) Print("Value: ", v); 13. ArrayFree(m); 14. } 15. //+------------------------------------------------------------------+ . . .
Fragmento 01
Note que neste fragmento, estou removendo uma linha do código. A tornando um comentário. No caso é a linha dez. Mas esta simples mudança, que poderia implicar no fato de não termos adicionado um número adequado de elementos para serem fatorados. Irá fazer com que o resultado seja o mostrado logo abaixo.
Imagem 06
Experimente fazer outras mudanças neste código 06 a fim de conseguir outros tipos de entendimentos. Pois isto irá lhe ajudar bastante no futuro.
Considerações finais
Este talvez tenha sido o artigo mais confuso para você iniciante. Já que aqui mostrei que nem sempre, teremos em um mesmo código, todas funções e procedimentos com nomes exclusivos. Podemos sim ter funções e procedimentos com um mesmo nome e isto é conhecido como sobrecarga. Apesar de ser algo possível, deve-se tomar cuidado ao se utilizar tal prática. Visto que isto muitas das vezes, torna tanto o código confuso para ser implementado, quanto também para vir a ser corrigido.
Espero que este artigo, venha a servir como uma forma de esclarecimento. Lhe tornando mais cuidadoso, a respeito de simplesmente não imaginar que uma função ou procedimento, já conhecidos. Terá ou deverá ter o mesmo comportamento de um outro procedimento ou função que esteja sendo implementada fazendo uso da sobrecarga.
No anexo, irei deixar parte dos códigos vistos neste artigo. Procure estudar este material, modificando os códigos do anexo, de modo a entender como a sobrecarga pode afetar, tanto o entendimento do código, quanto possíveis falhas que podem ocorrer, devido ao mal uso da sobrecarga. É melhor aprender como lidar com falhas. Quando os mecanismos são mais simples, do que tentar lidar com uma falha em algo mais complicado. Então estude esta questão da sobrecarga neste momento, onde tudo é mais simples. Pois conforme formos caminhando, as coisas se tornaram ainda mais complexas.
Aviso: Todos os direitos sobre esses materiais pertencem à MetaQuotes Ltd. É proibida a reimpressão total ou parcial.
Esse artigo foi escrito por um usuário do site e reflete seu ponto de vista pessoal. A MetaQuotes Ltd. não se responsabiliza pela precisão das informações apresentadas nem pelas possíveis consequências decorrentes do uso das soluções, estratégias ou recomendações descritas.






- Aplicativos de negociação gratuitos
- 8 000+ sinais para cópia
- Notícias econômicas para análise dos mercados financeiros
Você concorda com a política do site e com os termos de uso