Namespaces
Một không gian tên (namespace) là một khu vực được khai báo đặc biệt, trong đó các ID khác nhau được định nghĩa: biến, hàm, lớp, v.v. Nó được thiết lập bằng từ khóa namespace
:
namespace name_of_space {
// danh sách các định nghĩa hàm, lớp và biến
}
2
3
Việc áp dụng namespace
cho phép chia không gian tên toàn cục thành các không gian con. Tất cả các ID trong không gian tên đều có thể truy cập lẫn nhau mà không cần chỉ định. Toán tử ::
(toán tử phân giải ngữ cảnh) được sử dụng để truy cập các thành viên của không gian tên từ bên ngoài.
namespace ProjectData
{
class DataManager
{
public:
void LoadData() {}
};
void Func(DataManager& manager) {}
}
//+------------------------------------------------------------------+
//| Script program start function |
//+------------------------------------------------------------------+
void OnStart()
{
//--- làm việc với không gian tên ProjectData
ProjectData::DataManager mgr;
mgr.LoadData();
ProjectData::Func(mgr);
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
Không gian tên được sử dụng để sắp xếp mã dưới dạng các nhóm logic và tránh xung đột tên có thể xảy ra khi sử dụng nhiều thư viện trong một chương trình. Trong những trường hợp như vậy, mỗi thư viện có thể được khai báo trong không gian tên riêng của nó để truy cập rõ ràng vào các hàm và lớp cần thiết của từng thư viện.
Không gian tên có thể được khai báo trong nhiều khối trong một hoặc nhiều tệp. Trình biên dịch sẽ kết hợp tất cả các phần lại với nhau trong quá trình tiền xử lý và không gian tên kết quả sẽ chứa tất cả các thành viên được khai báo trong tất cả các phần. Giả sử chúng ta có lớp A được triển khai trong tệp bao gồm Sample.mqh
:
//+------------------------------------------------------------------+
//| Sample.mqh |
//+------------------------------------------------------------------+
class A
{
public:
A() {Print(__FUNCTION__);}
};
2
3
4
5
6
7
8
Chúng ta muốn sử dụng lớp này trong dự án của mình, nhưng chúng ta đã có lớp A. Để có thể sử dụng cả hai lớp và tránh xung đột ID, chỉ cần bao bọc tệp được bao gồm trong một không gian tên:
//--- khai báo lớp A đầu tiên
class A
{
public:
A() {Print(__FUNCTION__);}
};
//--- bao bọc lớp A từ tệp Sample.mqh trong không gian tên Library để tránh xung đột
namespace Library
{
#include "Sample.mqh"
}
//--- thêm một lớp khác vào không gian tên Library
namespace Library
{
class B
{
public:
B() {Print(__FUNCTION__);}
};
}
//+------------------------------------------------------------------+
//| Script program start function |
//+------------------------------------------------------------------+
void OnStart()
{
//--- sử dụng lớp A từ không gian tên toàn cục
A a1;
//--- sử dụng lớp A và B từ không gian tên Library
Library::A a2;
Library::B b;
}
//+------------------------------------------------------------------+
/*
Result:
A::A
Library::A::A
Library::B::B
*/
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
Không gian tên có thể được lồng nhau. Một không gian tên lồng có quyền truy cập không giới hạn vào các thành viên của không gian cha của nó, nhưng các thành viên của không gian cha không có quyền truy cập không giới hạn vào không gian tên lồng.
namespace General
{
int Func();
namespace Details
{
int Counter;
int Refresh() {return Func();}
}
int GetBars() {return(iBars(Symbol(), Period()));}
int Size(int i) {return Details::Counter;}
}
2
3
4
5
6
7
8
9
10
11
12
13
Không gian tên toàn cục
Nếu ID không được khai báo rõ ràng trong không gian tên, nó được coi là một phần ngầm định của không gian tên toàn cục. Để thiết lập ID toàn cục một cách rõ ràng, hãy sử dụng toán tử phân giải phạm vi mà không có tên. Điều này sẽ cho phép bạn phân biệt ID này với bất kỳ phần tử nào khác cùng tên nằm trong một không gian tên khác. Ví dụ, khi nhập một hàm:
#import "lib.dll"
int Func();
#import
//+------------------------------------------------------------------+
//| Some function |
//+------------------------------------------------------------------+
int Func()
{
return(0);
}
//+------------------------------------------------------------------+
//| Script program start function |
//+------------------------------------------------------------------+
void OnStart()
{
//+--- gọi hàm được nhập
Print(lib::Func());
//+--- gọi hàm của chúng ta
Print(::Func());
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
Trong trường hợp này, tất cả các hàm được nhập từ hàm DLL đã được bao gồm trong không gian tên cùng tên. Điều này cho phép trình biên dịch xác định rõ ràng hàm nào sẽ được gọi.
Xem thêm
Biến toàn cục, Biến cục bộ, Phạm vi hiển thị và thời gian sống của biến, Tạo và xóa đối tượng