객체 포인터
MQL5에서는 복잡한 유형 객체의 동적 생성이 가능합니다. 이것은 생성된 객체의 설명자를 반환하는 'new' 연산자를 사용하여 수행됩니다. 설명자의 사이즈는 8바이트입니다. MQL5의 객체 설명자는 구문적으로 C++ 포인터와 유사합니다.
예:
MyObject* hobject= new MyObject();
|
C++와 달리 위 예제의 'hobject' 변수는 메모리에 대한 포인터가 아니라 객체 설명자입니다. 또한 MQL5에서 함수에서 매개변수의 모든 객체는 참조로 전달되어야 합니다. 아래 예는 객체를 함수 매개변수로 전달하는 것을 보여줍니다:
class Foo
{
public:
string m_name;
int m_id;
static int s_counter;
//--- 생성자와 소멸자
Foo(void){Setup("noname");};
Foo(string name){Setup(name);};
~Foo(void){};
//--- Foo 객체 초기화
void Setup(string name)
{
m_name=name;
s_counter++;
m_id=s_counter;
}
};
int Foo::s_counter=0;
/+------------------------------------------------------------------+
//| 프로그램 시작 함수 스크립트 |
/+------------------------------------------------------------------+
void OnStart()
{
//--- 자동 생성으로 객체를 변수로 선언
Foo foo1;
//--- Transform passing object by reference
PrintObject(foo1);
//--- 객체에 대한 포인터를 선언하고 'new' 연산자를 사용하여 생성
Foo *foo2=new Foo("foo2");
//--- 참조로 객체에 대한 포인터를 전달하는 변형
PrintObject(foo2); // 객체에 대한 포인터는 컴파일러에 의해 자동으로 변환됩니다
//--- Foo 객체의 배열 선언
Foo foo_objects[5];
//--- 객체 배열 전달의 변형
PrintObjectsArray(foo_objects); // 객체 배열을 전달하기 위한 별도의 함수
//--- Foo 유형의 객체에 대한 포인터 배열 선언
Foo *foo_pointers[5];
for(int i=0;i<5;i++)
foo_pointers[i]=new Foo("foo_pointer");
//--- 포인터의 배열 전달의 변형
PrintPointersArray(foo_pointers); // 포인터 배열을 전달하기 위한 별도의 함수
//--- 완료하기 전에 포인터로 생성된 객체를 삭제해야 합니다
delete(foo2);
//--- 포인터의 배열을 제거
int size=ArraySize(foo_pointers);
for(int i=0;i<5;i++)
delete(foo_pointers[i]);
//---
}
/+------------------------------------------------------------------+
//| 객체는 항상 참조로 전달됩니다. |
/+------------------------------------------------------------------+
void PrintObject(Foo &object)
{
Print(__FUNCTION__,": ",object.m_id," Object name=",object.m_name);
}
/+------------------------------------------------------------------+
//| 객체의 배열을 전달 |
/+------------------------------------------------------------------+
void PrintObjectsArray(Foo &objects[])
{
int size=ArraySize(objects);
for(int i=0;i<size;i++)
PrintObject(objects[i]);
}
/+------------------------------------------------------------------+
//| 객체 포인터의 배열을 전달 |
/+------------------------------------------------------------------+
void PrintPointersArray(Foo* &objects[])
{
int size=ArraySize(objects);
for(int i=0;i<size;i++)
PrintObject(objects[i]);
}
/+------------------------------------------------------------------+
|
사용하기 전에 포인터를 체크하세요
잘못된 포인터에 액세스하려는 시도는 프로그램의 치명적 종료로 이어집니다. CheckPointer 함수는 포인터를 사용하기 전에 확인하는 기능입니다. 포인터는 다음과 같은 경우에 유효하지 않을 수 있습니다:
이 함수는 포인터의 유효성을 검사하는 데 사용될 수 있습니다. 0이 아닌 값은 이 포인터에서 데이터에 액세스할 수 있음을 나타냅니다.
class CMyObject
{
protected:
double m_value;
public:
CMyObject(void);
CMyObject(double value) {m_value=value;};
~CMyObject(void){};
//---
double Value(void) {return(m_value);}
};
/+------------------------------------------------------------------+
//| 프로그램 시작 함수 스크립트 |
/+------------------------------------------------------------------+
void OnStart()
{
//--- 초기화되지 않은 객체 생성
CMyObject *pointer;
if(CheckPointer(pointer)==POINTER_INVALID)
Print("1. pointer is ", EnumToString(CheckPointer(pointer)));
else
Print("1. pointer.Value()=", pointer.Value());
//--- 포인터 초기화
pointer=new CMyObject(M_PI);
if(CheckPointer(pointer)==POINTER_INVALID)
Print("2. pointer is ", EnumToString(CheckPointer(pointer)));
else
Print("2. pointer.Value()=", pointer.Value());
//--- 객체를 삭제
delete(pointer);
if(CheckPointer(pointer)==POINTER_INVALID)
Print("3. pointer is ", EnumToString(CheckPointer(pointer)));
else
Print("3. pointer.Value()=", pointer.Value());
}
/*
1. pointer is POINTER_INVALID
2. pointer.Value()=3.141592653589793
3. pointer is POINTER_INVALID
*/
|
포인터의 유효성을 빠르게 확인하려면 "!" 연산자를 사용할 수도 있습니다. (LNOT) CheckPointer 함수의 묵시적 호출을 통해 이를 확인합니다. 이는 좀더 깔끔하고 간략한 코드 작성을 가능하게 합니다. 아래는 이전 예에서 체크한 것입니다:
/+------------------------------------------------------------------+
//| 프로그램 시작 함수 스크립트 |
/+------------------------------------------------------------------+
void OnStart()
{
//--- 초기화되지 않은 객체 생성
CMyObject *pointer;
if(!pointer)
Print("1. pointer is ", EnumToString(CheckPointer(pointer)));
else
Print("1. pointer.Value()=", pointer.Value());
//--- 포인터 초기화
pointer=new CMyObject(M_PI);
if(!pointer)
Print("2. pointer is ", EnumToString(CheckPointer(pointer)));
else
Print("2. pointer.Value()=", pointer.Value());
//--- 객체를 삭제
delete(pointer);
if(!pointer)
Print("3. pointer is ", EnumToString(CheckPointer(pointer)));
else
Print("3. pointer.Value()=", pointer.Value());
}
/*
1. pointer is POINTER_INVALID
2. pointer.Value()=3.141592653589793
3. pointer is POINTER_INVALID
*/
|
연산자 "=="는 NULL을 빠르게 확인하는 데 사용됩니다. 일례: ptr==NULL 혹은 ptr!=NULL.
더 보기
변수, 변수 초기화, 가시성 범위 및 변수 수명, 객체 생성 및 삭제