Structures, Classes and Interfaces
Structures
Cấu trúc (structures
) là một tập hợp các phần tử của bất kỳ kiểu nào (trừ kiểu void ). Do đó, cấu trúc kết hợp dữ liệu có liên quan về mặt logic của các kiểu khác nhau.
Khai báo cấu trúc
Kiểu dữ liệu cấu trúc được xác định theo mô tả sau:
struct structure_name
{
elements_description
};
Tên cấu trúc không thể được sử dụng như một định danh (tên của một biến hoặc hàm). Cần lưu ý rằng trong MQL5, các thành phần cấu trúc theo sau nhau trực tiếp, không căn chỉnh. Trong C++, thứ tự như vậy được thực hiện với trình biên dịch bằng cách sử dụng lệnh sau:
#pragma pack(1)
Nếu bạn muốn căn chỉnh lại cấu trúc, hãy sử dụng các thành phần phụ trợ, "chất độn" có kích thước phù hợp.
VD:
struct trade_settings
{
uchar slippage; // giá trị của kích thước trượt giá cho phép 1 byte
char reserved1; // bỏ qua 1 byte
short reserved2; // bỏ qua 2 byte
int reserved4; // 4 byte khác được bỏ qua. đảm bảo căn chỉnh ranh giới 8 byte
double take; // giá trị của giá chốt lời
double stop; // giá trị giá của điểm dừng bảo vệ
};
Mô tả về các cấu trúc căn chỉnh như vậy chỉ cần thiết khi chuyển sang các hàm dll đã nhập.
Lưu ý : Ví dụ này minh họa dữ liệu được thiết kế không đúng. Tốt hơn hết là trước tiên hãy khai báo dữ liệu lớn
take
andstop
thuộc kiểudouble
, sau đó khai báo thành viênslippage
thuộc kiểuuchar
. Trong trường hợp này, biểu diễn dữ liệu bên trong sẽ luôn giống nhau bất kể giá trị được chỉ định trong#pragma pack()
là gì.
Nếu một cấu trúc chứa các biến kiểu chuỗi và/hoặc đối tượng của một mảng động, trình biên dịch sẽ gán một hàm tạo ngầm cho cấu trúc đó. Hàm tạo này đặt lại tất cả các thành viên cấu trúc kiểu chuỗi và khởi tạo đúng các đối tượng của mảng động.
Cấu trúc đơn giản
Các cấu trúc không chứa chuỗi, đối tượng lớp, con trỏ và đối tượng của mảng động được gọi là cấu trúc đơn giản. Các biến của cấu trúc đơn giản, cũng như mảng của chúng có thể được truyền dưới dạng tham số cho các hàm được nhập từ DLL.
Việc sao chép các cấu trúc đơn giản chỉ được phép trong hai trường hợp:
- Nếu các đối tượng thuộc cùng một kiểu cấu trúc
- Nếu các đối tượng được kết nối theo dòng dõi, nghĩa là một cấu trúc là hậu duệ của một cấu trúc khác.
Để cung cấp một ví dụ, chúng ta hãy phát triển cấu trúc tùy chỉnh CustomMqlTick
với nội dung giống hệt với cấu trúc MqlTick
tích hợp sẵn. Trình biên dịch không cho phép sao chép giá trị đối tượng MqlTick
vào đối tượng kiểu CustomMqlTick
. Việc ép kiểu trực tiếp sang kiểu cần thiết cũng gây ra lỗi biên dịch:
//--- sao chép các cấu trúc đơn giản của các kiểu khác nhau là bị cấm
my_tick1=last_tick; // compiler returns an error here
//--- ép kiểu các cấu trúc của các kiểu khác nhau cho nhau cũng bị cấm
my_tick1=(CustomMqlTick)last_tick; // trình biên dịch trả về lỗi ở đây
Do đó, chỉ còn lại một tùy chọn – sao chép các giá trị của các phần tử cấu trúc từng cái một. Vẫn được phép sao chép các giá trị cùng kiểu CustomMqlTick
.
CustomMqlTick my_tick1,my_tick2; //--- cho phép sao chép các đối tượng cùng kiểu với CustomMqlTick theo cách sau
my_tick2=my_tick1; //--- tạo một mảng từ các đối tượng của cấu trúc CustomMqlTick đơn giản và ghi giá trị vào đó
CustomMqlTick arr[2];
arr[0]=my_tick1;
arr[1]=my_tick2;
Hàm ArrayPrint()
được gọi để kiểm tra hiển thị giá trị mảng arr[]
trong nhật ký.
//+--------------------------------------------------------------------------------+
//| Hàm bắt đầu chương trình script |
//+--------------------------------------------------------------------------------+
void OnStart () { //--- phát triển cấu trúc tương tự như MqlTick tích hợp sẵn
struct CustomMqlTick
{
datetime time; // Thời gian cập nhật giá cuối cùng
double bid; // Giá thầu hiện tại
double ask; // Giá chào hiện tại
double last; // Giá hiện tại của giao dịch cuối cùng (Last)
ulong volume; // Khối lượng cho giá cuối cùng hiện tại
long time_msc; // Thời gian cập nhật giá cuối cùng tính bằng mili giây
uint flags; // Cờ tích tắc
};
//--- lấy giá tích tắc cuối cùng
MqlTick last_tick;
CustomMqlTick my_tick1,my_tick2;
//--- cố gắng sao chép dữ liệu từ MqlTick sang CustomMqlTick
if ( SymbolInfoTick ( Symbol (),last_tick))
{
//--- không được phép sao chép các cấu trúc đơn giản không liên quan
//1. my_tick1=last_tick; // trình biên dịch trả về lỗi ở đây
//--- việc ép kiểu các cấu trúc không liên quan với nhau cũng bị cấm
//2. my_tick1=(CustomMqlTick)last_tick;// trình biên dịch trả về lỗi ở đây
//--- do đó, hãy sao chép từng thành viên của cấu trúc
my_tick1.time=last_tick.time;
my_tick1.bid=last_tick.bid;
my_tick1.ask=last_tick.ask;
my_tick1.volume=last_tick.volume;
my_tick1.time_msc=last_tick.time_msc;
my_tick1.flags=last_tick.flags;
//--- được phép sao chép các đối tượng cùng kiểu với CustomMqlTick theo cách sau
my_tick2=my_tick1;
//--- tạo một mảng từ các đối tượng của cấu trúc CustomMqlTick đơn giản và ghi giá trị vào đó
CustomMqlTick arr[2];
arr[0]=my_tick1;
arr[1]=my_tick2;
ArrayPrint (arr);
//--- ví dụ về hiển thị giá trị của mảng chứa các đối tượng của CustomMqlTick kiểu
/* [time] [bid] [ask] [last] [volume] [time_msc] [flags]
[0] 2017.05.29 15:04:37 1.11854 1.11863 +0.00000 1450000 1496070277157 2
[1] 2017.05.29 15:04:37 1.11854 1.11863 +0.00000 1450000 1496070277157 2
*/
}
else
Print ( "SymbolInfoTick() không thành công, lỗi = " , GetLastError ());
}