기고글 토론 "MQL5에서 객체 포인터 사용"

 

새로운 기고글 MQL5에서 객체 포인터 사용 가 게재되었습니다:

기본적으로 MQL5의 모든 오브젝트는 참조로 전달되지만 오브젝트 포인터를 사용할 가능성이 있습니다. 그러나 객체가 초기화되지 않을 수 있으므로 포인터 검사를 수행해야 합니다. 이 경우 MQL5 프로그램은 심각한 오류로 종료되고 언로드됩니다. 자동으로 생성된 객체는 이러한 오류를 일으키지 않으므로 이 점에서 매우 안전합니다. 이 글에서는 개체 참조와 개체 포인터의 차이점을 이해하고 포인터를 사용하는 보안 코드를 작성하는 방법을 고려합니다.

MQL5에서는 코드에서 클래스 유형 변수를 추가로 사용하기 위해 고유한 클래스를 작성할 수 있습니다. MQL5의 객체 생성 및 파괴 순서글에서 이미 알고 있듯이 구조 및 클래스는 자동 및 동적의 두 가지 방법으로 생성할 수 있습니다.

객체를 자동으로 생성하려면 클래스 유형 변수를 선언하기만 하면 됩니다. 시스템이 자동으로 생성하고 초기화합니다. 개체를 동적으로 생성하려면new 연산자를 개체 포인터에 명시적으로 적용해야 합니다.

그러나 자동으로 생성되는 개체와 동적으로 생성되는 개체의 차이점은 무엇이며, 개체 포인터를 반드시 사용해야 할 때와 개체를 자동으로 생성하기에 충분할 때 무엇입니까? 이 주제는 이 글 의 주제입니다. 첫 번째로 개체 작업시 발생할 수 있는 몇 가지 함정에 대해 논의하고 이를 수정하는 방법을 고려해보겠습니다.

작성자: MetaQuotes

 

텍스트의 소스 코드는 첨부된 파일과 일치해야 하며, 특히 GetCriticalError_Unsafe.mq5 목록에서는 파일에서와 같이 pstatus 대신 존재하지 않는 변수 상태를 참조합니다.

그리고 각 CShape 상속자 클래스에서 자체 변수 유형을 정의하는 이유는 무엇입니까?

그리고 이에 대한 설명도 듣고 싶습니다. GetCriticalError_OnDemand 예제에서 GetCriticalError_Unsafe로 전환 할 때 전체 변경 사항은 실제로 함수 인수의 유형을 CHello * 개체에서 CHello & 개체 로 변경하는 것으로 축소되었습니다. 동시에 함수 호출은 변경되지 않은 채로 유지되었으며 포인터(CHello *)가 전달되었습니다. 이 경우 저자의 말에 따르면"우리는 다시 심각한 오류가 발생합니다. 요점은 객체가 참조로 전달되는 경우 초기화되지 않은 객체가 전달되는 함수 호출 단계에서 치명적인 오류가 발생한다는 것입니다." 그러나 이 경우 함수에 전달되는 것은 참조가 아니라 포인터입니다. 문제는 그것이 어디에서 발생하는지입니다. MQL5에서 포인터를 참조로 암시적으로 변환하는 데 사용하는 규칙에 대해 자세히 설명해 주시겠습니까? 또는 문서에서 해당 내용이 설명되어 있는 곳을 가리켜 주세요. 컴파일러가 엄격한 타입을 지원한다면 필요한 타입의 인수를 가진 함수가 없기 때문에 예제는 컴파일에 실패할 것입니다.

 
marketeer писал(а) # :

텍스트의 소스 코드는 첨부된 파일과 일치해야 하며, 특히 GetCriticalError_Unsafe.mq5 목록에서 파일에서처럼 pstatus 대신 존재하지 않는 변수 상태에 대한 참조가 만들어져 있습니다.

문서와 파일에서 수정했습니다.

 
marketeer писал(а) # :

각 CShape 후속 클래스에서 자체 유형 변수를 정의하는 이유는 무엇인가요?

원칙적으로 이 멤버는 어디에도 사용되지 않으므로 제거할 수 있습니다. 이론적으로는 자손 클래스에서 객체 유형에 의존하는 함수를 구현하는 데 사용할 수 있습니다.
 
marketeer писал(а) # :
이 문제에 대한 설명도 듣고 싶습니다. GetCriticalError_OnDemand 예제에서 GetCriticalError_Unsafe로 전환할 때 전체 변경 사항은 사실상 함수 인수의 유형을 CHello *pobject에서 CHello &pobject로 변경하는 것으로 축소되었습니다. 동시에 함수 호출은 변경되지 않은 채로 유지되었으며 포인터(CHello *)가 전달되었습니다. 이 경우 저자의 말에 따르면"우리는 다시 심각한 오류가 발생합니다. 요점은 객체가 참조로 전달되는 경우 초기화되지 않은 객체가 전달되는 함수 호출 단계에서 치명적인 오류가 발생한다는 것입니다." 하지만 이 경우에는 참조가 아닌 포인터가 함수에 전달됩니다. 이 문제가 어디서 발생하는지 궁금합니다. MQL5에서 포인터를 참조로 암시적으로 변환하는 데 사용하는 규칙에 대해 자세히 설명해 주시겠습니까? 또는 문서에서 해당 내용이 설명되어 있는 곳을 가리켜 주세요. 컴파일러가 엄격한 타입을 지원하는 경우 필요한 타입의 인수를 가진 함수가 없기 때문에 예제는 컴파일에 실패할 것입니다.
매개변수를 포인터로 받는 함수가 명시적으로 정의되어 있으면 해당 함수가 사용됩니다. 그러한 함수가 없는 경우 객체 포인터는 자동으로 객체에 대한 참조로 변환되고 참조로 객체를 받는 함수가 사용됩니다.
 
Rosh писал(а) # :
원칙적으로 이 멤버는 어디에도 사용되지 않으므로 제거할 수 있습니다. 이론적으로는 자손에서 객체 유형에 따라 달라지는 함수를 구현하는 데 사용할 수 있습니다.
예제의 현재 소스에 따르면 특정 유형의 도형 객체에 CShape::type 외에 CLine::type과 같은 두 가지 유형 변수가 있다는 "레이크"를 얻는다는 것을 올바르게 이해합니까? 이상적으로는 기본 클래스에서 하나가 있어야 합니다.
 
Rosh писал(а) # :
매개변수를 포인터로 받아들이는 함수가 명시적으로 정의되어 있으면 그 함수가 사용됩니다. 그러한 함수가 없는 경우 객체의 포인터는 자동으로 객체에 대한 참조로 캐스팅되고 참조로 객체를 받아들이는 함수가 사용됩니다.
참조와 포인터에 관한 암시적 변환의 방향에 대해 읽을 수 있는 곳이 있나요? 특히 참조에서 포인터로의 역변환도 가능한가요?
 
marketeer писал(а) # :
참조와 포인터에서 수행되는 암시적 변환의 방향에 대해 읽을 수 있는 곳이 있나요? 특히, 참조에서 포인터로의 역변환도 수행되나요?
아니요, 객체의 포인터를 가져오려면GetPointer()를 사용하세요.
Документация по MQL5: Общие функции / GetPointer
Документация по MQL5: Общие функции / GetPointer
  • www.mql5.com
Общие функции / GetPointer - Документация по MQL5
 
marketeer писал(а) # :
예제의 현재 소스에 따르면 특정 유형의 도형 객체에는 CShape::type 외에 CLine::type과 같은 두 가지 유형 변수가 있다는 "갈퀴"가 있다는 것을 올바르게 이해했나요? 이상적으로는 기본 클래스에서 하나가 있어야 합니다.

네, 맞습니다. 작성하신 대로 각 자손에 두 개의 유형 변수가 있습니다. 자손의 코드가 복사되었기 때문에 이런 일이 발생했습니다. 기본 클래스의 멤버를 자손이 직접 사용할 수 있도록 하려면 보호 지정자를 사용하여 정의하거나 이 멤버에 대한 공용 get 및 set 메서드를 기본 클래스에 선언해야 합니다.

예를 들면 다음과 같습니다:

//+------------------------------------------------------------------+
//|demo_inheritance.mq5 |
//| 저작권 2010, MetaQuotes Software Corp.
//|http://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "2010, MetaQuotes Software Corp."
#property link      "http://www.mql5.com"
#property version   "1.00"
//+------------------------------------------------------------------+
//||
//+------------------------------------------------------------------+
class CBase
  {
private:
   int               type;
public:
                     CBase(){type=0;}
   int               GetType(){return(type);}
  };
//+------------------------------------------------------------------+
//||
//+------------------------------------------------------------------+
class CSon: CBase
  {
private:
   int               type;
public:
                     CSon(){type=2;}
   void              PrintType();
  };
//+------------------------------------------------------------------+
//||
//+------------------------------------------------------------------+
void CSon::PrintType()
  {
   Print("CSon.type =",type);
   Print("CBase.type =",CBase::GetType());
  }
//+------------------------------------------------------------------+
//| 스크립트 프로그램 시작 기능|
//+------------------------------------------------------------------+
void OnStart()
  {
//---
   CSon  son;
   son.PrintType();
   int father_type=son.GetType();
  }
//+------------------------------------------------------------------+
 
인용:

"이 예제는 매우 간단하여 오류를 찾는 것이 어렵지 않습니다. 그러나 mql5 프로그램에 수백 또는 수천 줄이 포함되어 있는 경우 이러한 오류를 찾는 것이 훨씬 더 복잡해질 수 있습니다. 특히 프로그램 동작의 비정상적인 상황 조건이 특정 시장과 같이 예측할 수 없는 요인에 따라 달라지는 경우에는 더욱 그렇습니다."

어떻게요?:-)

 
커플의 특성이 어떤 식으로든 다른 경우입니다.