Thành viên tĩnh
Cho đến nay, chúng ta đã xem xét các trường và phương thức của một lớp mô tả trạng thái và hành vi của các đối tượng thuộc lớp đó. Tuy nhiên, trong các chương trình, đôi khi cần lưu trữ một số thuộc tính hoặc thực hiện các thao tác trên toàn bộ lớp, thay vì trên các đối tượng của nó. Những thuộc tính của lớp như vậy được gọi là tĩnh và được mô tả bằng từ khóa static
được thêm trước kiểu dữ liệu. Chúng cũng được hỗ trợ trong các cấu trúc và liên hợp.
Ví dụ, chúng ta có thể đếm số lượng hình dạng mà người dùng đã tạo trong một chương trình vẽ. Để làm điều này, trong lớp Shape
, chúng ta sẽ mô tả biến tĩnh count
(Shapes5.mq5
).
class Shape
{
private:
static int count;
protected:
...
Shape(int px, int py, color back, string t) :
coordinates(px, py),
backgroundColor(back),
type(t)
{
++count;
}
public:
...
static int getCount()
{
return count;
}
};
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
Biến này được định nghĩa trong phần private
và do đó không thể truy cập từ bên ngoài.
Để đọc giá trị hiện tại của bộ đếm, một phương thức tĩnh công khai getCount()
được cung cấp. Về lý thuyết, vì các thành viên tĩnh được định nghĩa trong ngữ cảnh của một lớp, chúng chịu các hạn chế về khả năng hiển thị theo bộ sửa đổi của phần mà chúng nằm trong đó.
Chúng ta sẽ tăng bộ đếm lên 1 trong hàm tạo có tham số của Shape
, và loại bỏ hàm tạo mặc định. Do đó, mỗi thể hiện của một hình dạng thuộc bất kỳ kiểu dẫn xuất nào sẽ được tính đến.
Lưu ý rằng một biến tĩnh phải được định nghĩa rõ ràng (và tùy chọn khởi tạo) bên ngoài khối lớp:
static int Shape::count = 0;
Các biến tĩnh của lớp tương tự như biến toàn cục và biến tĩnh bên trong hàm (xem phần Biến tĩnh) ở chỗ chúng được tạo khi chương trình bắt đầu và bị xóa trước khi chương trình được dỡ bỏ. Do đó, không giống như các biến đối tượng, chúng phải tồn tại từ đầu dưới dạng một thể hiện duy nhất.
Trong trường hợp này, việc khởi tạo bằng 0 có thể được bỏ qua vì, như chúng ta biết, các biến toàn cục và tĩnh được đặt về 0 theo mặc định. Các mảng cũng có thể là tĩnh.
Trong định nghĩa của một biến tĩnh, chúng ta thấy việc sử dụng toán tử chọn ngữ cảnh đặc biệt ::
. Với nó, một tên biến đầy đủ được hình thành. Bên trái của ::
là tên của lớp mà biến thuộc về, và bên phải là định danh của nó. Rõ ràng, tên đầy đủ là cần thiết, vì trong các lớp khác nhau, các biến tĩnh có cùng định danh có thể được khai báo, và cần một cách để tham chiếu duy nhất đến từng biến trong số chúng.
Toán tử ::
cùng được sử dụng để truy cập không chỉ các biến tĩnh công khai của lớp mà còn các phương thức. Cụ thể, để gọi phương thức getCount
trong hàm OnStart
, chúng ta sử dụng cú pháp Shape::getCount()
:
void OnStart()
{
for(int i = 0; i < 10; ++i)
{
Shape *shape = addRandomShape();
shape.draw();
delete shape;
}
Print(Shape::getCount()); // 10
}
2
3
4
5
6
7
8
9
10
11
Vì số lượng hình dạng được chỉ định (10) hiện đang được tạo ra, chúng ta có thể xác minh rằng bộ đếm hoạt động chính xác.
Nếu bạn có một đối tượng lớp, bạn có thể tham chiếu đến một phương thức hoặc thuộc tính tĩnh thông qua giải tham chiếu thông thường (ví dụ, shape.getCount()
), nhưng cách ghi như vậy có thể gây hiểu nhầm (vì nó che giấu việc đối tượng thực sự không được truy cập).
Lưu ý rằng việc tạo các lớp dẫn xuất không ảnh hưởng đến các biến và phương thức tĩnh theo bất kỳ cách nào: chúng luôn được gán cho lớp mà chúng được định nghĩa. Bộ đếm của chúng ta là như nhau cho tất cả các lớp hình dạng dẫn xuất từ Shape
.
Bạn không thể sử dụng this
bên trong các phương thức tĩnh vì chúng được thực thi mà không gắn với một đối tượng cụ thể. Ngoài ra, từ một phương thức tĩnh, bạn không thể trực tiếp, mà không giải tham chiếu bất kỳ biến kiểu đối tượng nào, gọi một phương thức lớp thông thường hoặc truy cập trường của nó. Ví dụ, nếu bạn gọi draw
từ getCount
, bạn sẽ nhận được lỗi "access to non-static member or function":
static int getCount()
{
draw(); // lỗi: 'draw' - truy cập đến thành viên hoặc hàm không tĩnh
return count;
}
2
3
4
5
Vì lý do tương tự, các phương thức tĩnh không thể là ảo.
Liệu có thể, bằng cách sử dụng các biến tĩnh, tính toán không phải tổng số hình dạng, mà thống kê của chúng theo loại không? Có, điều đó là khả thi. Nhiệm vụ này được để lại cho việc tự học. Những người quan tâm có thể tìm một trong những ví dụ triển khai trong script Shapes5stats.mq5
.