Xem thêm

Giới Thiệu Về Static Trong C++

Huy Erick
Static trong ngôn ngữ lập trình C++ là một cách để định nghĩa các thành viên của một lớp mà không phụ thuộc vào các đối tượng của lớp đó. Khi khai báo một thành...

Static trong lập trình c' class='hover-show-link replace-link-1748'>ngôn ngữ lập trình c ++ là một cách để định nghĩa các thành viên của một lớp mà không phụ thuộc vào các đối tượng của lớp đó. Khi khai báo một thành viên của một lớp là static, thì bất kể có bao nhiêu đối tượng của lớp được tạo ra, chỉ có một bản sao duy nhất của thành viên static đó tồn tại.

Một thành viên static chỉ cần được khởi tạo một lần và được chia sẻ cho tất cả các đối tượng của lớp. Tất cả các dữ liệu static sẽ được khởi tạo về giá trị 0 khi đối tượng đầu tiên của lớp được tạo ra.

Trong c+ +, chúng ta không thể khởi tạo thành viên static trong định nghĩa lớp, nhưng chúng ta có thể khai báo lại biến static bên ngoài lớp đó bằng cách sử dụng toán tử phân giải phạm vi :: để xác định lớp sở hữu. Hãy cùng tìm hiểu chi tiết hơn về điều này qua bài viết dưới đây.

I. Định Nghĩa Static Trong C++

Static trong C++ dùng để định nghĩa dữ liệu của lớp và không phải là dữ liệu của đối tượng. Dữ liệu static trong C++ tồn tại như một biến toàn cục, có nghĩa là nó xuất hiện trước khi bạn khởi tạo đối tượng của lớp và chỉ tồn tại duy nhất.

Các thành viên static có thể là public, private hoặc protected. Static cũng có thể được sử dụng để khai báo thành viên dữ liệu dùng chung cho mọi thể hiện của lớp. Điều này có nghĩa là chỉ có một bản sao duy nhất của thành viên static tồn tại trong suốt quá trình chạy của chương trình, và nó được dùng chung cho tất cả các thể hiện của lớp, bất kể lớp đó có bao nhiêu thể hiện.

Định Nghĩa Static Trong C++

Ví dụ:

#include  using namespace std;  class Rectangle {     private:         int width;         int length;         static int count;      public:         void set(int w, int l);         int area();         Rectangle() {             count++;         }         Rectangle(int x, int y) {             count++;             set(x, y);         } };  void Rectangle::set(int w, int l) {     width = w;     length = l; }  int Rectangle::area() {     return width * length; }  int Rectangle::count = 0;  int main() {     Rectangle r1(2, 4);     Rectangle r2(1, 2);     Rectangle r3;     cout << "Number of rectangles created: " << Rectangle::count << endl;     return 0; }

Trong ví dụ trên, chúng ta có một lớp Rectangle có hai thành viên dữ liệu width và length, và một thành viên static count để đếm số lượng các hình chữ nhật đã được tạo ra. Mỗi khi một đối tượng Rectangle được tạo ra, chúng ta tăng biến count lên để đếm số lượng hình chữ nhật đã được tạo ra. Cuối cùng, chúng ta in ra số lượng hình chữ nhật đã được tạo ra bằng cách gọi Rectangle::count.

II. Biến Static Trong Hướng Đối Tượng C++

Trong hướng đối tượng C++, chúng ta có thể khai báo một biến static để đếm số lượng các đối tượng đã được tạo ra trong một lớp. Ví dụ dưới đây sẽ minh họa cách khai báo và sử dụng một biến static trong một lớp Rectangle:

#include  using namespace std;  class Rectangle {     private:         int width;         int length;         static int count;      public:         void set(int w, int l);         int area();         Rectangle() {             count++;         }         Rectangle(int x, int y) {             count++;             set(x, y);         } };  void Rectangle::set(int w, int l) {     width = w;     length = l; }  int Rectangle::area() {     return width * length; }  int Rectangle::count = 0;  int main() {     Rectangle r1(2, 4);     Rectangle r2(1, 2);     Rectangle r3;     cout << "Number of rectangles created: " << Rectangle::count << endl;     return 0; }

Trong ví dụ trên, chúng ta có một biến static count để đếm số lượng các hình chữ nhật đã được tạo ra. Mỗi khi một đối tượng Rectangle được tạo ra, chúng ta tăng biến count lên để đếm số lượng hình chữ nhật đã được tạo ra. Cuối cùng, chúng ta in ra số lượng hình chữ nhật đã được tạo ra bằng cách gọi Rectangle::count.

III. Hàm Static Trong Hướng Đối Tượng C++

Trong hướng đối tượng C++, chúng ta cũng có thể khai báo một hàm static trong một lớp, nghĩa là hàm chỉ thuộc về lớp mà không thuộc về bất kỳ đối tượng cụ thể nào của lớp đó. Ví dụ dưới đây sẽ minh họa cách khai báo và sử dụng một hàm static trong một lớp Rectangle:

#include  using namespace std;  class Rectangle {     private:         int width;         int length;         static int count;      public:         void set(int w, int l);         static int getCount();         int area();         Rectangle() {             count++;         }         Rectangle(int x, int y) {             count++;             set(x, y);         } };  void Rectangle::set(int w, int l) {     width = w;     length = l; }  int Rectangle::area() {     return width * length; }  int Rectangle::count = 0;  int Rectangle::getCount() {     return count; }  int main() {     Rectangle r1(2, 4);     Rectangle r2(1, 2);     Rectangle r3;     cout << "Number of rectangles created: " << Rectangle::getCount() << endl;     return 0; }

Trong ví dụ trên, chúng ta có một hàm static getCount để trả về số lượng các hình chữ nhật đã được tạo ra. Chúng ta có thể gọi hàm static này bằng cách sử dụng phạm vi truy cập :: để gọi nó. Cuối cùng, chúng ta in ra số lượng hình chữ nhật đã được tạo ra bằng cách gọi Rectangle::getCount.

IV. Thành Viên Static Của Class

Trong C++, chúng ta cũng có thể khai báo các hàm thành viên static trong một lớp. Bằng cách khai báo một hàm thành viên là static trong C++, bạn làm cho nó độc lập với bất kỳ đối tượng cụ thể nào của lớp. Một hàm thành viên static có thể được gọi mà không cần có bất kỳ đối tượng nào của lớp tồn tại, và các hàm static chỉ có thể được truy cập bằng cách sử dụng tên lớp và toán tử phân giải phạm vi :: trong C++.

Một hàm thành viên static chỉ có thể truy cập các thành viên dữ liệu static, các hàm thành viên static khác và bất kỳ hàm nào khác từ bên ngoài lớp đó. Các hàm thành viên static có phạm vi lớp và chúng không có sự truy cập đến con trỏ this của lớp trong C++. Bạn có thể sử dụng một hàm thành viên để xử lý các kiểm tra nếu một số đối tượng của lớp đã được tạo.

Ví dụ:

#include  using namespace std;  class Box {     public:         Box(double len) : length(len) {             count++;         }          static int getCount() {             return count;         }      private:         double length;         static int count; };  int Box::count = 0;  int main() {     Box box1(2.4);     Box box2(4.5);     cout << "Number of boxes: " << Box::getCount() << endl;     return 0; }

Trong ví dụ trên, chúng ta có một lớp Box với một thành viên dữ liệu length và một thành viên static count để đếm số lượng các hộp đã được tạo ra. Mỗi khi một đối tượng Box được tạo ra, chúng ta tăng biến count lên để đếm số lượng hộp đã được tạo ra. Cuối cùng, chúng ta in ra số lượng hộp đã được tạo ra bằng cách gọi Box::getCount.

V. Khi Nào Nên Sử Dụng Biến Static

Biến static được sử dụng khi chúng ta chỉ cần một bản sao của biến và không cần thay đổi nó. Trong trường hợp chúng ta khai báo biến bên trong một phương thức, chúng sẽ trở thành biến cục bộ chỉ hoạt động trong phạm vi phương thức đó.

Các biến được khai báo static thường được chia sẻ trên tất cả các thể hiện của một lớp. Khi bạn tạo nhiều phiên bản của một lớp, biến static này sẽ được chia sẻ giữa tất cả chúng. Do đó, tại bất kỳ thời điểm nào, chỉ có một giá trị duy nhất của biến static này.

Vì chỉ có một bản sao của biến static có sẵn cho tất cả các thể hiện, mã this.permament sẽ dẫn đến lỗi biên dịch vì có thể nhớ lại rằng this.variablename tham chiếu đến tên biến cụ thể. Do đó, những biến tĩnh phải được truy cập trực tiếp, như được chỉ ra trong mã.

Khi Nào Nên Sử Dụng Biến Static

VI. Const Static Trong C++ là gì?

Trong C++ và C, từ khóa const static được sử dụng để ẩn hằng số trong các mô-đun khác. Một biến được khai báo const static có ý nghĩa là không thay đổi và chỉ có thể truy cập từ các mô-đun khác.

Trong C++, từ khóa const static mặc định là ở cấp độ không gian tên (namespace-level). Điều này có nghĩa là biến được khai báo const trong một tệp nguồn có thể truy cập từ các tệp nguồn khác trong cùng một không gian tên.

Ví dụ:

#include  using namespace std;  namespace Math {     const static float PI = 3.14159; }  int main() {     cout << "The value of PI is: " << Math::PI << endl;     return 0; }

Trong ví dụ trên, chúng ta có một không gian tên Math và một biến PI được khai báo là const static trong không gian tên đó. Chúng ta có thể truy cập biến PI bằng cách sử dụng Math::PI.

VII. Bài Tập C++ OOP Giá Trị Của Biến Static

Biến static (static variables)

Biến static trong C++ có khả năng lưu giữ giá trị của nó cho đến khi chương trình kết thúc, ngay cả khi ra khỏi khối lệnh chứa biến đó. Biến static chỉ cần được khai báo một lần duy nhất và tiếp tục tồn tại xuyên suốt quá trình chạy của chương trình.

Dưới đây là một ví dụ đơn giản cho thấy sự khác biệt giữa việc sử dụng biến cục bộ và biến static:

#include  using namespace std;  void incrementAndPrint() {     int value = 1; // automatic duration by default     ++value;     cout << value << endl; }  int main() {     incrementAndPrint();     incrementAndPrint();     incrementAndPrint();     return 0; }

Mỗi khi hàm incrementAndPrint được gọi, một biến có tên là value được tạo ra và được gán giá trị 1. Hàm incrementAndPrint sẽ tăng giá trị của biến value lên 1 và in ra giá trị đó. Khi hàm incrementAndPrint hoàn thành tác vụ, biến value sẽ bị hủy. Kết quả in ra màn hình sẽ là:

2 2 2

Bây giờ, chúng ta thêm từ khóa static trước khai báo biến value:

#include  using namespace std;  void incrementAndPrint() {     static int s_value = 1; // static duration variable     ++s_value;     cout << s_value << endl; }  int main() {     incrementAndPrint();     incrementAndPrint();     incrementAndPrint();     return 0; }

Lần này, vì biến s_value được khai báo với từ khóa static, nó sẽ chỉ được khởi tạo một lần duy nhất, dù hàm incrementAndPrint được gọi nhiều lần. Mỗi lần hàm incrementAndPrint được gọi, giá trị của biến s_value sẽ được tăng thêm 1 và vẫn được lưu giữ lại cho đến khi chương trình kết thúc. Kết quả in ra màn hình sẽ là:

2 3 4

Hàm static (static functions)

Từ khóa static cũng có thể được sử dụng trên các hàm, thường là các hàm được đặt bên trong các lớp hoặc các kiểu dữ liệu (gọi là phương thức). Trong bài viết này, mình sẽ lấy một ví dụ về việc sử dụng hàm static trong một lớp mẫu:

#include  using namespace std;  struct Test {     static void foo() {         cout << "Called static function: foo" << endl;     } };  int main() {     Test::foo();     return 0; }

Trong ví dụ trên, hàm foo được gọi mà không cần tạo ra thực thể của kiểu Test. Chúng ta có thể thấy rằng hàm foo được gọi mà không cần tạo đối tượng của lớp Test.

Điểm đáng lưu ý khi sử dụng hàm static trong struct/class là chúng không thể truy cập vào thành viên không phải là static trong struct/class đó:

struct Test {     int value;     void nonstatic_foo() { }     static void foo() {         value = 1; // error         nonstatic_foo(); // error     } };

Hàm static không thể truy cập thành viên không phải là static trong cùng một lớp.

1