Các thành phần tĩnh
+ Thành phần dữ liệu được khai báo bằng từ khoá static gọi là tĩnh, ví dụ: Class a { Private: Static int ts ; // thành phần tĩnh Int x; .... } ; + Thành phần tĩnh được cấp phát một vùng nhớ cố ...
+ Thành phần dữ liệu được khai báo bằng từ khoá static gọi là tĩnh, ví dụ:
Class a { Private: Static int ts ; // thành phần tĩnh Int x; .... } ;
+ Thành phần tĩnh được cấp phát một vùng nhớ cố định. Nó tồn tại ngay cả khi lớp chưa có một đối tượng nào cả.
+ Thành phần tĩnh là chung cho cả lớp, nó không phải là riêng của mỗi đối tượng. Ví dụ xét 2 đối tượng:
A u,v ; // khai báo 2 đối tượng
Thì giữa các thành phần x và ts có sự khác nhau như sau:
U.x và v.x có 2 vùng nhớ khác nhau
U.ts và v.ts chỉ là một, chúng cùng biểu thị một vùng nhớ
Thành phần ts tồn tại ngay khi u và v chưa khai báo
+ Để biểu thị thành phần tĩnh, ta có thể dùng tên lớp, ví du: đối với ts thì 3 cách viết sau là tương đương:
a::ts u.ts v.ts
+ Khai báo và khởi gán giá trị cho thành phần tĩnh
Thành phần tĩnh sẽ được cấp phát bộ nhớ và khởi gán giá trị ban đầu bằng một câu lệnh khai báo đặt sau định nghĩa lớp (bên ngoài các hàm, kể cả hàm main), theo các mẫu:
Int a::ts ; // khởi gán cho ts giá trị 0 Int a::ts = 1234; // khởi gán cho ts giá trị 1234Khi chưa khai báo thì thành phần tĩnh chưa tồn tại.
Xét chương trình sau:
#include <conio.h> #include <iostream.h> Class hdbh // hoá đơn bán hàng { Private: Char *tenhang ; // tên hàng Double tienban ; // tiền bán Static int tshd ; // tổng số hoá đơn Static double tstienban ; // tổng số tiền bán Public: Static void in() { Cout <<" " << tshd; Cout <<" " << tstienban; } } ; Void main() { Hdbh::in(); Getch(); }
tshd và tstienban chưa khai báo, nên chưa tồn tại. Vì vậy các câu lệnh in giá trị các thành phần này trong phương thức in là không logic. Khi dịch chương trình, sẽ nhận được các thông báo lỗi (tại phương thức in) như sau:
Undefined symbol hdbh::tshd in module ...
Undefined symbol hdbh::tstienban in module ...
Có thể sửa chương trình trên bằng cách đưa vào các lệnh khai báo các thành phần tĩnh tshd và tstienban như sau:
//ct4_14.cpp // thanh phan tinh // lop hdbh (hoa don ban hang) #include <conio.h> #include <iostream.h> Class hdbh { Private: int shd ; Char *tenhang ; Double tienban ; Static int tshd ; Static double tstienban ; Public: Static void in() { Cout <<" " << tshd; Cout <<" " << tstienban; } } ; Int hdbh::tshd=5; Double hdbh::tstienban=20000.0; Void main() { Hdbh::in(); Getch(); }
Xét một ví dụ về quản lý các hoá đơn bán hàng. Mỗi hoá đơn có: tên hàng, số tiền bán. Rõ ràng các thuộc tính nói trên là riêng của mỗi hoá đơn. Mặt khác nếu chúng ta quan tâm đến tổng số hoá đơn đã bán, tổng số tiền đã bán, thì các thông tin này là chung. Vì vậy khi thiết kế lớp hdbh (hoá đơn bán hàng) , thì ta có thể đưa vào 4 thành phần dữ liệu là:
Tenhang (tên hàng)
Tienban (tiền bán)
Tshd (tổng số hoá đơn)
Tstienban (tổng số tiền bán)
Các thuộc tính tenhang và tienban là riêng của mỗi hoá đơn, nên chúng được chọn là các thuộc tính thông thường. Còn các thuộc tính tshd và tstienban là chung cho cả lớp nên chúng được chọn là các thuộc tính tĩnh.
+ Có 2 cách viết phương thức tĩnh:
Cách 1: dùng từ khoá static đặt trước định nghĩa phương thức viết bên trong định nghĩa lớp (như phương thưc in() ví dụ cuối của mục 9.1).
Cách 2: nếu phương thức xây dựng bên ngoài định nghĩa lớp, thì dùng từ khoá static đặt trước khai báo phương thức bên trong định nghĩa lớp. Chú ý không cho phép dùng từ khoá static đặt trước định nghĩa phương thức viết bên ngoài định nghĩa lóp.
+ Phương thức tĩnh là chung cho cả lớp, nó không lệ thuộc vào một đối tượng cụ thể, nó tồn tại ngay khi lớp chưa có đối tượng nào (xem ví dụ trong mục 9.1).
+ Lời gọi phương thức tĩnh:
Có thể xuất phát từ một đối tượng nào đó (như vẫn dùng khi gọi các phương thức khác)
Có thể dùng tên lớp
Xét lớp hdbh trong mục 9.1 và xét các câu lênh:
Hdbh u, v;
Khi đó để gọi phương thức tĩnh in() có thể dùng một trong các lệnh sau:
U.in();
V.in();
Hdbh::in();
+ Vì phương thức tĩnh là độc lập với các đối tượng, nên không thể dùng phương thức tĩnh để xử lý dữ liệu của các đối tượng chủ thể trong lời gọi phương thức tĩnh. Nói cách khác không cho phép truy nhập tới các thuộc tính (trư thuộc tính tĩnh) trong thân phương thức tĩnh. Điều đó cũng đồng nghĩa với việc không cho phép dùng con trỏ this trong phương thức tĩnh.
Nếu lập phương thức tĩnh in() để in các thuộc tính của lớp hdbh như sau:
Class hdbh { Private: Int shd ; Char *tenhang ; Double tienban ; Static int tshd ; Static double tstienban ; Public: Static void in() { Cout <<" " << tshd; Cout <<" " << tstienban; Cout <<" " << tenhang; Cout <<" " << tienban; } } ;
thì sẽ bị lỗi, vì trong thân phương thức tĩnh không cho phép truy nhập đến các thuộc tính tenhang và tienban.
Xét bài toán quản lý hoá đơn bán hàng. Mỗi hoá đơn có 2 dữ liêu là tên hàng và tiền bán. Sử dụng hàm tạo để tạo ra các hoá đơn, dùng hàm huỷ để bỏ đi (loại đi) các hoá đơn không cần lưu trữ, dùng một phương thức để sửa chữa nội dung hoá đơn (nhập lại tiền bán). Vấn đề đặt ra là sau một số thao tác: tạo, sửa và huỷ hoá đơn thì tổng số hoá đơn còn lại là bao nhiêu và tổng số tiền trên các hoá đơn còn lại là bao nhiêu?
Chương trình dưới đây nhằm đáp ứng yêu cầu đặt ra.
//ct4_14.cpp // thanh phan tinh // lop hdbh (hoa don ban hang) #include <conio.h> #include <iostream.h> Class hdbh { Private: Char *tenhang ; Double tienban ; Static int tshd ; Static double tstienban ; Public: Hdbh(char *tenhang1=null,double tienban1=0.0 ) { Tienban=tienban1; Tenhang=tenhang1; ++tshd; Tstienban += tienban; } ~hdbh() { --tshd; Tstienban -= tienban; } Void sua(); Static void in(); } ; Int hdbh::tshd=0; Double hdbh::tstienban=0; Void hdbh::in() { Cout <<" tong so hoa don: " << tshd; Cout <<" tong so tien: " << tstienban; } Void hdbh::sua() { Cout << " ten hang: " << tenhang; Cout << " tien ban : " << tienban; Tstienban -= tienban; Cout << " sua tien ban thanh : " ; Cin >> tienban; Tstienban += tienban; } Void main() { Hdbh *h1 = new hdbh("xi mang",2000); Hdbh *h2 = new hdbh("sat thep",3000); Hdbh *h3 = new hdbh("ti vi",4000); Clrscr(); Hdbh::in(); Getch(); Delete h1; Hdbh::in(); Getch(); H2->sua(); Hdbh::in(); Getch(); Delete h3; Hdbh::in(); Getch(); }