Bug de compilador com parâmetro de modelo = vazio* - página 6

 
Alexey Navoykov:

Tudo está funcionando bem, por que você está inventando isso?

No diário de bordo que obtemos:

vazio A::~A()
vazio B::~B()

Porque é que eu até caí nessa...

Bem, então eu sinto muito, não sabia que você poderia fazer isso, MKL não é muito C++. No lado positivo, a remoção do vazio* é UB.

 

Fórum sobre comércio, sistemas automatizados de comércio e testes de estratégia comercial

Nova versão do MetaTrader 5 build 1930: Janela de gráficos flutuantes e biblioteca .Net em MQL5

Alexey Navoykov, 2018.12.15 02:44

Prezados Desenvolvedores. Anteriormente em um dos tópicos discutimos o defeito do compilador que permite a fundição implícita de uma classe base a uma classe derivada, mas parece ter passado despercebido por você. Este é um problema sério, dificultando a verificação de erros e se torna uma dor de cabeça constante quando se usa ativamente o OOP. Tal fundição deve ser apenas explícita. Esta é uma regra geral tanto para C++ quanto para C#.

class A {  };

class B : public A { };

A* a = new A;

B* b = a;  // Нет ошибки компиляции!

void f(B*) {  }

void OnInit()
{ 
  f(a);  // Нет ошибки компиляции!
}  

E o que fazer aqui?

class A {  };

class B : public A { };

A* a = new A;

void* v = a;

B* b = v;  // Нет ошибки компиляции!


Este comportamento também deve ser considerado um erro?

 
Alexey Navoykov:

Se o estilizador torna o código difícil de ler, então por que diabos usá-lo?

Para mim, um modelador só é bom quando TODAS as suas regras podem ser flexivelmente personalizadas.

Portanto, se você ler o código de outra pessoa em um formulário impresso (ou em um fórum, como aqui).

 
fxsaber:
Sobre os parênteses
((A*)(b.GetPtr())).f(); // Доп. скобки, чтобы подчеркнуть, что именно имелось в виду, не полагаясь на приоритеты.

Bem, talvez isso o enfatize, mas para mim só vai confundir. Mas olhando para esta expressão, não consigo entender imediatamente de quem é o método que está sendo chamado aqui. Mas nas duas linhas anteriores, é claro ao mesmo tempo.

Para entender o que está sendo feito você deve abrir todos os parênteses. Quanto mais parênteses houver, mais tempo é desperdiçado para descobrir o que está acontecendo, especialmente se não estiverem separados por espaços.

 
Alexey Navoykov:

Bem, talvez isso o enfatize, mas para mim só confundirá. Mas olhando para esta expressão, não consigo entender imediatamente de quem é chamado aqui o método. Mas nas duas linhas anteriores, tudo está claro de uma só vez.

Para entender exatamente o que está sendo feito, é preciso abrir todos os parênteses. Quanto mais parênteses - mais tempo é gasto para entender o que está acontecendo. Especialmente se eles não estiverem separados por espaços de nenhuma forma.

Parênteses adicionais não são para leitura - deixe que o modelador se encarregue disso, colocando espaços.

Mas para o autocontrole enquanto se escreve. Por que eu deveria confiar nas prioridades de alguém quando escrevo em uma área sensível, ao mesmo tempo em que tenho consciência de que estou escrevendo código de plataforma cruzada (e não necessariamente apenas MT4/5) que pode ser portado para outros idiomas? Os colchetes adicionais eliminam completamente a influência das prioridades lingüísticas. Tudo se torna absolutamente inequívoco. Por causa disso, há uma confiabilidade de 100% de que nada falhará neste lugar após a próxima construção.


Além disso, quando eu ler este inferno de parênteses, terei que gastar tempo na compreensão absoluta do que eu quero dizer aqui. E sobre o tema da visibilidade.

bool a = (1 < 2) && (3 < 4);
bool b = 1 < 2 && 3 < 4;

vamos perguntar, qual opção é mais visual?

 
fxsaber:

Este comportamento também conta como um erro?

É claro que sim. Isto é a mesma coisa.

Então acontece que nada é gerado onde um problema é realmente possível e pelo menos avisos são necessários (ou mesmo um erro de compilação). Mas eles não poupam nenhum aviso quando parênteses são forçados ) E algumas pessoas aqui até propõem proibir a compilação sem parênteses e nos ameaçam com smackheads ) É assim que vivemos...

 
Alexey Navoykov:

É claro. Isto é a mesma coisa.

Então acontece que se existe um problema real e pelo menos um aviso é necessário (ou mesmo um erro de compilação), nada é mostrado. Mas com parênteses eles não poupam nenhum aviso ) E algumas pessoas aqui até propõem proibir a compilação sem parênteses e ameaçam bater em você ) É assim que vivemos...

Então você também precisa de um aviso? Que tipo de padrão duplo é esse: em ambos os lugares o comportamento é inequívoco, mas com parênteses você é contra advertências, e aqui você está a favor disso?

Você precisa de um aviso para não cometer erros difíceis de serem encontrados. Portanto, a dificuldade é uma avaliação subjetiva. Assim, com parênteses você não comete erros, e aqui você pode. E para mim é o contrário.

Então, a qual de nós as regras de emissão de advertências devem ser ajustadas?

 
Ilya Malev:

Eu não sabia sobre StringConcatenate, é uma pena que no MT5 ele tenha sido redesenhado e não possa ser usado sem cordel s. E o StringFormat é muito mais rápido no 4

E em geral, por alguma razão, esta operação de "sondagem" de um ponteiro através de um fio é quase duas vezes mais lenta em 5, embora em geral funcione mais rápido lá, às vezes por uma ordem

é possível que StringConcatenate() seja 32 bit, você não sabe, os desenvolvedores já escreveram que os metaetiters em 5 e 4 são os mesmos, talvez por causa da compatibilidade eles o "embrulharam

Ontem tentei resolver seu problema com o dynamic_cast< >. O problema é que o MQL não permite desreferenciar os indicadores. a função em um método de classe pode ser chamada via dynamic_cast<C_myclass >( func( ) ), você pode obter um ponteiro para a classe via dynamic_cast< > mas o que fazer com um ponteiro? - você pode reatribuir o vazio *ptr , mas não faz sentido porque o ponteiro não pode ser desreferenciado de qualquer maneira

 
pavlick_:

Se você quiser eliminar o CArayObject, você tem que fazer uma substituição (como esta https://www.mql5.com/ru/forum/170952/page110#comment_9894796) sobre a classe base e colocá-los em uma matriz (possivelmente sua), mas então você não precisará mais de vazio*.

Não sou contra o vazio*, ele é necessário, mas em uma capacidade diferente.

Não vejo o ponto de código por referência (embora eu também não utilize bibliotecas padrão). Se colocar um objeto em um array envolve a criação de uma cópia dele, então o método de atribuição ou construtor de cópia deve ser declarado e descrito explicitamente naquela classe, caso contrário, nenhum invólucro ajudará de qualquer forma. Se você só precisa colocar uma referência a um objeto em uma matriz, você não precisa de nenhum invólucro (por quê?).

A propósito, você parece não saber que se(p) apagar p não é idêntico a "se pontos de referência a um objeto dinâmico existente, apagá-lo" em mql.

class A{};

void OnStart()
 {
  A *a=new A;
  if(a) Print("Кукареку!");
  if(CheckPointer(a)==POINTER_DYNAMIC) Print("Динамический объект существует и может быть удален");
  else                                 Print("Объект не существует, либо он автоматический");
  delete a;
  if(a) Print("Кукареку!");
  if(CheckPointer(a)==POINTER_DYNAMIC) Print("Динамический объект существует и может быть удален");
  else                                 Print("Объект не существует, либо он автоматический");
 }
 
fxsaber:

E sobre o tema da visibilidade.

vamos perguntar, qual deles é mais claro?

Bem, se foi assim que o modelador o formatou para você:

1 < 2 && 3 < 4;

então, mais uma vez, é com o estilista. Eu nunca faria isso em meu código. Eu faria desta maneira:

1<2 && 3<4
либо
1 < 2  &&  3 < 4
Razão: