OOP, mql5의 템플릿 및 매크로, 미묘함 및 사용 기술 - 페이지 2

 
Ilya Malev :

나는 많은 통계 선언 상황을 겪었습니다. stat가 다시 선언된 경우 전역 수준(OnInit 이전)에서 초기화된 클래스의 필드입니다. 필드는 클래스 설명 바로 뒤에 있고 해당 인스턴스의 전역 변수를 선언하기 전에 정적 필드를 초기화하는 데 문제가 발생한 적이 없습니다(이 경우 전역으로 간주되고 클래스 인스턴스보다 먼저 초기화되기 때문에 제가 이해하는 바). 즉, 메서드와 함수 내에서 정적 변수 선언을 거부하기만 하면 되며 문제가 없습니다.

네 맞습니다. 일반 클래스에서는 즉시 초기화됩니다. 그러나 템플릿에서 - 아니요:

 template < typename T>
class A
{
 public : 
   static int a;
};

template < typename T>
int A::a= 10 ;

int f() { return A< int >::a; }

int a= f();

void OnStart ()
{
   Print (a); // Результат: 0
};
 
Alexey Viktorov :

메서드와 함수 내에서 정적 변수 선언을 완전히 거부할 수는 없지만 적어도 정적 변수가 있는 메서드나 함수로 다른 정적 변수를 초기화하지 마십시오.

이 예에서 정적 int b 변수가 먼저 초기화되지만 int a(int n) 함수 내부에 있는 정적 int f 변수는 아직 초기화되지 않았으므로 결과적으로 쓰레기가 됩니다.

그건 그렇고, 예, 이것은 또 다른 버그입니다. 저것들. 정적/전역 변수를 별도로 초기화하는 것 외에도 정적 변수 자체를 잘못된 순서로 초기화하기도 합니다. 그리고 이제 이것은 훨씬 더 심각한 문제입니다. 여기서 " 정적 변수가 있는 메서드나 함수로 다른 정적 변수를 초기화하지 마십시오."라고 말합니다. 이것을 실제로 관찰하기 위해 어떻게 제안합니까? 각 기능은 독립적이며 자체적으로 존재합니다. 변경될 수 있는 자체 구현이 있습니다. 이전에는 정적 변수가 없다고 가정하고 추가하기로 결정했습니다. 그리고 그것은 어딘가에서 무언가가 잘못 작동하기 시작할 수 있다는 것을 의미합니다. 왜냐하면 거기에는 함수에 정적 변수가 없다는 사실이 깔려 있기 때문입니다. 그리고 그것을 어떻게 통제할 것인가?

 
그리고 일반적으로 그러한 결정은 나에게 이해할 수 없으며 이것 또는 저것을 포기할 필요가 있다고 말합니다. 왜 거부합니까? 무엇 때문에? 문제를 해결할 수 있고 자신을 부인하지 않는 경우. 뭐, 각자의 선택은 있겠지만...
 
Alexey Navoykov :

그건 그렇고, 예, 이것은 또 다른 버그입니다. 저것들. 정적/전역 변수를 별도로 초기화하는 것 외에도 정적 변수 자체를 잘못된 순서로 초기화하기도 합니다. 그리고 이제 이것은 훨씬 더 심각한 문제입니다. 여기서 " 정적 변수가 있는 메서드나 함수로 다른 정적 변수를 초기화하지 마십시오."라고 말합니다. 이것을 실제로 관찰하기 위해 어떻게 제안합니까? 각 기능은 독립적이며 자체적으로 존재합니다. 변경될 수 있는 자체 구현이 있습니다. 이전에는 정적 변수가 없다고 가정하고 추가하기로 결정했습니다. 그리고 그것은 어딘가에서 무언가가 잘못 작동하기 시작할 수 있다는 것을 의미합니다. 왜냐하면 거기에는 함수에 정적 변수가 없다는 사실이 깔려 있기 때문입니다. 그리고 그것을 어떻게 통제할 것인가?

예, 여기에는 문제가 없습니다. 함수에 의한 변수 초기화를 포기하는 것으로 충분하며 모든 것이 제자리에 들어갈 것입니다.

 int a( int n)
{
 static int f= 7 ;
 return (f+=n);
}

void OnTick ()
{
 static int b;
 b=a( 9 );
}
그래서 그것은 강타와 함께 작동합니다. 뭐가 문제야??? 한줄로?
 
Alexey Viktorov :

그래서 그것은 강타와 함께 작동합니다. 뭐가 문제야??? 한줄로?

자, 여기에서는 논리가 다르다는 것을 이해하고 계십니까? 그렇다면 호출할 때마다 값을 할당한다면 왜 b를 정적으로 선언할까요?
 
Alexey Navoykov :
자, 여기에서는 논리가 다르다는 것을 이해하고 계십니까? 그렇다면 호출할 때마다 값을 할당한다면 왜 b를 정적으로 선언할까요?

동의한다. 급하게 나는 약간의 트릭을 했다. 하지만 결국 변수 b는 어떤 조건에서 값을 할당받을 수 있고, 조건에 따라 9 대신에 값을 함수에 전달할 수 있다.


그러나 귀하의 예에서 변수 'a'는 전역 수준에서 초기화되어야 합니까?

 template < typename T>
class A
{
 public : 
   static int a;
};

template < typename T>
int A::a= 10 ;

int f() { return A< int >::a; }

int a= f();

void OnStart ()
{
   Print (a); // Результат: 0
};

스크립트에는 다른 옵션이 없지만 EA에서는 전역 수준에서 변수를 선언하고 OnInit()에서 초기화할 수 있습니다.

초기화 순서를 이해하고 따르는 것으로 충분합니다. 먼저 전역 변수, 정적 변수, 코드에 나타나는 지역 변수 순입니다.

함수에 의한 변수 초기화 를 방지하기 위한 문서의 권장 사항을 위반한 것은 이 예제입니다. 개발자가 그러한 경고를 작성하는 것이 어디가 가능하고 어디가 불가능한지를 설명하는 것보다 쉬웠습니다.

예제에서 정적을 제거하고 원하는 결과를 얻으십시오.

 
Alexey Viktorov :

그러나 귀하의 예에서 변수 'a'는 전역 수준에서 초기화되어야 합니까?

필요는 없지만 나에게는 더 편리합니다. 그것이 상수라면(그리고 전역 가시성에서 코드를 읽을 수 있는 경우 대부분 상수가 선언됨) 여기에는 다른 선택이 없습니다.

스크립트에는 다른 옵션이 없지만 EA에서는 전역 수준에서 변수를 선언하고 OnInit()에서 초기화할 수 있습니다 .

초기화 순서 를 이해하고 따르는 것으로 충분합니다 . 먼저 전역 변수, 정적 변수, 코드에 나타나는 지역 변수 순입니다.

함수에 의한 변수 초기화 를 방지하기 위한 문서의 권장 사항을 위반한 것은 이 예제입니다. 개발자가 그러한 경고를 작성하는 것이 어디가 가능하고 어디가 불가능한지를 설명하는 것보다 쉬웠습니다.

예제에서 정적을 제거 하고 원하는 결과를 얻으십시오.

노란색으로 강조 표시된 모든 항목에 대해 한 가지 질문이 있습니다. 왜? 나는 이미 문제를 해결하는 방법을 찾았습니다.
 
마지막 페이지에서 파일을 업데이트했습니다. 작은 버그를 수정했습니다.
 
Alexey Navoykov :

필요는 없지만 나에게는 더 편리합니다. 이것이 상수인 경우(그리고 전역 가시성에서 코드를 읽을 수 있는 경우 대부분 상수가 선언됨) 다른 선택은 없습니다.

노란색으로 강조 표시된 모든 항목에 대해 한 가지 질문이 있습니다. 왜? 나는 이미 문제를 해결하는 방법을 찾았습니다.

당신은 그것을 만드는 방법을 찾았습니다.

 
Alexey Navoykov :

네 맞습니다. 일반 클래스에서는 즉시 초기화됩니다. 그러나 템플릿에서 - 아니요:

이 클래스의 인스턴스가 하나 이상 생성되기 전에 초기화 단계에서 클래스의 정적 필드 를 사용하려고 합니다. 제 생각에는 이것은 변태입니다 ... 이것이 모든 것이 잘 작동하는 방법입니다.

 template < typename T>
class A
{
 public : 
  A(){}
   static int a;
   int f(){ return a;}
};

template < typename T>
int A::a= 10 ;

A< int > _a;


int a= _a.f();

void OnStart ()
{
   Print (a);
};
캡슐화 원칙은 일반적으로 이러한 필드가 공개가 아닌 비공개여야 한다고 제안합니다.