템플릿 매개변수가 있는 컴파일러 버그 = void* - 페이지 6

 
Alexey Navoykov :

예, 모든 것이 잘 작동합니다. 무엇을 발명하고 있습니까?

로그에서 다음을 얻습니다.

무효 A::~A()
무효 B::~B()

그리고 내가 왜 이것에 빠졌는지...

글쎄요, 죄송합니다. 가능한지 몰랐습니다. MKL은 C ++이 아닙니다. 플러스 측면에서 void*를 제거하는 것은 UB입니다.

 

거래, 자동 거래 시스템 및 거래 전략 테스트에 관한 포럼

MetaTrader 5 플랫폼 빌드 1930의 새 버전: MQL5의 플로팅 차트 창 및 .Net 라이브러리

알렉세이 나보이코프 , 2018.12.15 02:44

친애하는 개발자. 이전 분기 중 하나에서 기본 클래스를 파생 클래스로 암시적으로 캐스팅할 수 있는 컴파일러 결함에 대해 논의했지만 분명히 이것은 눈치채지 못한 것 같습니다. 이것은 오류를 제어하기 어렵게 만드는 심각한 문제 이며 OOP를 적극적으로 사용함에 따라 끊임없는 골칫거리가 됩니다. 이러한 캐스팅은 명시적이어야 합니다. 이것은 C++와 C#의 일반적인 규칙입니다.

 class A {  };

class B : public A { };

A* a = new A;

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

void f(B*) {  }

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

여기는 어때?

 class A {  };

class B : public A { };

A* a = new A;

void * v = a;

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


이 동작도 버그로 간주해야 합니까?

 
Alexey Navoykov :

스타일리스트가 읽을 수 있는 코드에서 코드를 읽기 어렵게 만든다면 그러한 스타일리스트가 그에게 적합하지 않을 수 있습니까?

저에게 스타일러는 모든 규칙을 유연하게 사용자 지정할 수 있을 때만 좋습니다.

글쎄, 다른 사람의 코드를 인쇄된 형태로 읽는다면(또는 여기와 같은 포럼에서).

 
fxsaber :
추가 정보 괄호
((A*)(b.GetPtr())).f(); // Доп. скобки, чтобы подчеркнуть, что именно имелось в виду, не полагаясь на приоритеты.

글쎄요, 그것은 당신을 강조할 수 있지만, 저에게는 반대로 혼란스러울 뿐입니다. 그리고 저는 이 표현을 바로 보고 있는데 여기에서 누구의 메소드가 호출되는지 이해할 수 없습니다. 그리고 앞의 두 줄에서 모든 것이 한 번에 명확합니다.

정확히 무엇을 하는지 이해하려면 모든 괄호를 열어야 합니다. 괄호가 많을수록 무슨 일이 일어나고 있는지 이해하는 데 더 많은 시간이 소요됩니다. 특히 어떤 식 으로든 공백으로 구분되지 않은 경우.

 
Alexey Navoykov :

글쎄, 네, 그것은 당신을 강조 할 수 있지만 나에게는 반대로 혼란 스러울뿐입니다. 그리고 저는 이 표현을 바로 보고 있는데 여기에서 누구의 메소드가 호출되는지 이해할 수 없습니다. 그리고 앞의 두 줄에서 모든 것이 한 번에 명확합니다.

정확히 무엇을 하는지 이해하려면 모든 괄호를 열어야 합니다. 괄호가 많을수록 무슨 일이 일어나고 있는지 이해하는 데 더 많은 시간이 소요됩니다. 특히 어떤 식 으로든 공백으로 구분되지 않은 경우.

여기에 추가. 대괄호를 읽을 수 없습니다. 스타일러 가 공백을 두어 이 작업을 수행하도록 합니다.

그리고 글을 쓰는 동안 자제를 위해 . 민감한 장소에 글을 쓸 때 다른 사람의 우선 순위에 의존해야 하는 동시에 다른 언어로 포팅할 수 있는 크로스 플랫폼 코드(꼭 MT4/5만은 아닐 수도 있음)를 작성하고 있음을 인식해야 하는 이유는 무엇입니까? 추가하다. 괄호는 언어 우선 순위의 영향을 완전히 제거했습니다. 모든 것이 절대적으로 명확해집니다. 덕분에 100% 신뢰성이 나타나며 다음 빌드 후에 이 위치에서 아무 것도 깨지지 않을 것입니다.


게다가 내가 이 괄호로 묶인 지옥을 읽을 때, 나는 여기서 내가 정확히 무엇을 의미하는지 절대적으로 이해하는 시간을 가질 수밖에 없을 것이다. 그리고 가시성에 대해

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

어느 것이 더 나은지 물어봅시다.

 
fxsaber :

이 동작도 버그로 간주해야 합니까?

틀림없이. 이것은 동일합니다.

따라서 문제가 실제로 가능하고 최소한 경고가 필요한 경우(일반적 으로 컴파일 오류 ) 아무 것도 발행되지 않습니다. 그러나 대괄호를 부과하면 경고를 아끼지 않습니다.) 그리고 여기에 일부는 대괄호없이 편집을 금지하고 수갑으로 위협하기까지 제안합니다) 이것이 우리가 사는 방식입니다 ...

 
Alexey Navoykov :

틀림없이. 이것은 동일합니다.

따라서 문제가 실제로 가능하고 최소한 경고가 필요한 경우(일반적 으로 컴파일 오류 ) 아무 것도 발행되지 않습니다. 그러나 대괄호를 부과하면 경고를 아끼지 않습니다.) 그리고 여기에 일부는 대괄호없이 편집을 금지하고 수갑으로 위협하기까지 제안합니다) 이것이 우리가 사는 방식입니다 ...

그래서 여전히 경고가 필요합니까? 어떤 종류의 이중 잣대: 두 곳 모두에서 행동이 모호하지 않지만 대괄호를 사용하면 경고에 반대하지만 여기 - FOR?

또한 미묘한 실수를 하지 않도록 경고도 필요합니다. 따라서 난이도는 주관적인 평가입니다. 여기 대괄호를 사용하면 실수하지 않지만 여기서는 할 수 있습니다. 그리고 저에게는 그 반대입니다.

그렇다면 경고 발령 규칙을 조정해야 하는 사람은 누구입니까?

 
Ilya Malev :

저는 StringConcatenate에 대해 몰랐습니다. MT5에서 다시 작성되어 더 이상 string s 없이 사용할 수 없다는 것이 유감입니다. 그리고 네 번째에는 StringFormat이 눈에 띄게 빨라집니다.

그리고 일반적으로 어떤 이유로 상위 5개에서 문자열을 통해 포인터를 "단순화"하는 이 작업은 거의 두 배 느립니다. 기본적으로 모든 것이 더 빠르게 작동하지만 때로는 몇 배 정도 더 느립니다.

어떤 이유로 StringConcatenate()가 32비트일 가능성이 있습니다. 개발자는 이미 5에서 동일하고 4에서 동일한 Metaetitors가 호환성으로 인해 "래핑"되었을 수 있다고 작성했습니다.

dynamic_cast<>로 실험할 수 있습니다. 어제 문제 를 해결하려고 했지만 문제는 MQL이 포인터 역참조를 허용하지 않는다는 것입니다. dynamic_cast<C_myclass >( func( ) ) 특정 클래스 메서드를 호출하면 dynamic_cast<>를 통해 클래스에 대한 포인터를 얻을 수 있지만 이러한 포인터로 무엇을 해야 할까요? - void *ptr을 재할당할 수 있지만 의미가 없습니다. 여전히 포인터를 역참조할 수 없습니다.

 
pavlick_ :

CArayObject를 덤프에 보내려면 기본 클래스 위에 래퍼(예: https://www.mql5.com/ru/forum/170952/page110#comment_9894796) 를 만들고 이를 배열(아마도 당신의 것)이지만 void*는 필요하지 않습니다.

나는 무효*에 반대하는 것이 아니라 필요하지만 다른 자격으로 필요합니다.

(표준 라이브러리를 사용하지 않지만) 참조로 코드의 요점을 볼 수 없습니다. 배열에 개체를 배치하는 데 복사본 생성이 포함되는 경우 이 클래스에서 할당 메서드 또는 복사 생성자를 명시적으로 선언하고 설명해야 합니다. 그렇지 않으면 래퍼가 도움이 되지 않습니다. 배열의 객체에 대한 참조만 넣어야 하는 경우 래퍼가 필요하지 않습니다(갑자기 왜?)

그건 그렇고, 당신은 if(p) delete p가 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 :

그리고 가시성에 대해

어느 것이 더 나은지 물어봅시다.

글쎄, 스타일리스트가 당신을 다음과 같이 포맷했다면:

 1 < 2 && 3 < 4 ;

그런 다음 이 스타일리스트에게 모든 질문을 반복합니다. 따라서 아픈 머리를 건강한 머리 탓으로 돌릴 필요가 없습니다. 나는 내 코드에서 그렇게하지 않을 것입니다. 그리고 나는 이것을 할 것입니다 :

 1 < 2 && 3 < 4
либо
1 < 2   &&   3 < 4