Static Trong C++

Static Trong C++

Chúng ta có thể định nghĩa các thành viên lớp là static bởi dùng từ khóa static trong C++. Khi chúng ta khai báo 1 thành viên của 1 lớp là static, lúc đó dù cho có bao nhiêu đối tượng của lớp được tạo, thì sẽ chỉ mang 1 bản sao của thành viên static.

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

Chúng ta không thể khởi tạo thành viên static trong định nghĩa lớp, nhưng nó có thể được định nghĩa bên ngoài lớp đó bởi việc khai báo lại biến static như trong ví dụ sau, sử dụng toán tử phân giải phạm vi :: để nhận diện lớp nào sở hữu nó. Hãy cùng Techacademy tìm hiểu chi tiết qua bài viết dưới đây nhé.

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

Static trong c++ là dữ liệu của lớp không phải là dữ liệu của đối tượng. Static trong c++ tồn tại như 1 biến toàn cục. Hay nói cách khác dữ liệu static xuất hiện trước lúc bạn khởi tạo đối tượng của lớp, và nó chỉ tồn tại duy nhất.

Các thành viên static có thể là public, private hoặc protected.

Static ngoài khai báo biến còn có thể khai báo hàm.

Đối với class, static 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:

  • Một bản duy nhất tồn tại trong suốt quá trình chạy của chương trình.
  • 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 C++
Định Nghĩa Static C++

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

Ví dụ mình sẽ khai báo một biến static, int count, biến này dùng để đếm số lượng các hình chữ nhật đã được tạo ra.

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);
  }
}

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);
  }
}

 

Như vậy khi một đối tượng được tạo chúng ta sẽ tăng count lên để thực hiện đúng ý đồ đếm hình chữ nhật.

Tuy nhiên chúng ta không thể gán trước giá trị ban đầu của static trong class mà chúng ta phải gán giá trị cho nó ở ngoài class.

ví dụ

int main() {
    int Rectangle::count = 0; // Sau khi khởi tạo giá trị đầu mình tạo minh họa 3 hình chữ nhật Rectangle r1(2,4); Rectangle r2(1,2); Rectangle r3;}

    int main() {
      int Rectangle::count = 0;
      // Sau khi khởi tạo giá trị đầu mình tạo minh họa 3 hình chữ nhật
      Rectangle r1(2, 4);
      Rectangle r2(1, 2);
      Rectangle r3;
    }

 

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

Ví dụ về static trong c++

Ví dụ bên trên chỉ rõ biến static count không phải là dữ liệu của đối tượng như width và length mà nó là dữ liệu của class và chỉ tồn tại duy nhất.

Để sử dụng, gán hoặc lấy giá trị của static bạn sử dụng phạm vi truy xuất để gọi nó

//Ví dụ khởi tạo ban đầu
int Rectangle::count = 0;
 
//Gọi biến static:
Rectangle::count

Lưu ý thêm ở phần khai báo mình để static count ở private, nên bên ngoài class không thể dùng phạm vi truy xuất đến truy cập (Như cách gọi Rectangle::count ) Nhưng việc khai báo và gán giá trị ban đầu như int Rectangle::count = 0; là được phép.

Để dùng Rectangle::count bạn có thể khai báo biến static này ở public hoặc viết thêm hàm static get giá trị count này.

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

Hàm static có vai trò cũng như biến static. Nghĩa là khi bạn đã khai báo class nhưng chưa tạo ra đối tượng như Rectangle r1(2,4) thì chúng ta vẫn truy cập được biến count như ví dụ trên. Vậy ở phần hàm static cũng có vai trò như vậy, hàm này sẽ là tồn tại duy nhất của class.

Mình sẽ khai báo thêm static int getCount() ở thuộc tính public

a. Code cụ thể về static

class Rectangle
{
    private:
        int width;
        int length;
        static int count;
    public:
        void set(int w, int l);
 
        static int getCount()
        {
            return count;
        }
 
        int area();
        Rectangle()
        {
            count++;
        }
        Rectangle(int x, int y) 
        { 
            count++; 
            set(x,y);
        }
}

b. Gọi hàm static

Bạn có thể gọi hàm static bằng cách sau:

  • Gọi Rectangle::getCount() ở ngoài class hoặc bên trong class
  • Gọi getCount() Bên trong class.
Hàm Static Trong Hướng Đối Tượng C++
Hàm Static Trong Hướng Đối Tượng C++

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

Hàm thành viên static trong C++

Bằng việc khai báo 1 hàm thành viên là static trong C++, bạn làm 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 ngay cả lúc không có đối tượng nào của lớp tồn tại và những hàm static được truy cập chỉ bởi 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 chỉ có thể truy cập thành viên dữ liệu static, những hàm thành viên static khác và bất kỳ hàm khác từ bên ngoài lớp đó.

Các hàm thành viên static có một 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 1 hàm thành viên để xác định có hay không một số đối tượng của lớp đã được tạo.

Bạn thử ví dụ sau để hiểu khái niệm của hàm thành viên static trong C++:

#include <iostream>
 
using namespace std;

class Box
{
   public:
      static int biendemDT;
      // phan dinh nghia Constructor
      Box(double dai=1.0, double rong=1.0, double cao=1.0)
      {
         cout <<"Constructor duoc goi." << endl;
         chieudai = dai;
         chieurong = rong;
         chieucao = cao;
         // gia tri cua biendemDT tang len moi khi doi tuong duoc tao
         biendemDT++;
      }
      double theTich()
      {
         return chieudai * chieurong * chieucao;
      }
      static int layBienDem()
      {
         return biendemDT;
      }
   private:
      double chieudai;     // Chieu dai cua mot box
      double chieurong;    // Chieu rong cua mot box
      double chieucao;     // Chieu cao cua mot box
};

// khoi tao thanh vien static cua lop Box
int Box::biendemDT = 0;

int main(void)
{
  
   // in tong so doi tuong duoc tao truoc khi tao cac doi tuong.
   cout << "So doi tuong ban dau la: " << Box::layBienDem() << endl;

   Box Box1(2.4, 4.2, 2.2);    // khai bao box1
   Box Box2(4.5, 2.0, 3.2);    // khai bao box2

   // in tong so doi tuong duoc tao sau khi tao cac doi tuong.
   cout << "Tong so doi tuong sau khi tao la: " << Box::layBienDem() << endl;

   return 0;
}

Biên dịch và chạy chương trình C++ trên sẽ cho kết quả sau:

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

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

Biến static được dùng lúc chỉ cần một bản sao của biến. vì vậy trường hợp bạn khai báo biến bên trong phương thức thì không dùng biến như vậy, nó sẽ trở thành cục bộ chỉ hoạt động ..

Các biến được khai báo static thường được chia sẻ trên tất cả các trường hợp của một lớp.

Các biến được khai báo static thường được chia sẻ trên tất cả các trường hợp của một lớp. Khi bạn tạo đa dạng phiên bản của lớp VariableTest Biến này vĩnh viễn được chia sẻ trên tất cả chúng. Do đó, tại bất kỳ thời điểm nhất định nào, sẽ chỉ có 1 giá trị chuỗi được chứa trong biến vĩnh viễn.

Vì chỉ có 1 bản sao của biến có sẵn cho tất cả các trường hợp, 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
Khi Nào Nên Sử Dụng Biến Static

VI. Const Static’ Có Nghĩa Là Gì Trong C Và C ++?

Const static’ có nghĩa là gì trong C và C ++

Tôi đã thấy điều này trong 1 số mã ở đây trên StackOverflow và tôi không thể tìm ra nó làm gì. Sau đó, tôi thấy 1 số câu trả lời nhầm lẫn trên các diễn đàn khác. Tôi đoán tốt nhất là nó được dùng trong C để ẩn hằng số fookhỏi những mô-đun khác. Điều này có đúng không? Nếu vậy, tại sao mọi người sẽ dùng nó trong bối cảnh C ++ nơi bạn có thể tạo ra nó private?

Câu trả lời:

+ Nó có dùng trong cả C và C ++.

Như bạn đã đoán, staticphần giới hạn phạm vi của nó cho đơn vị biên dịch đó. Nó cũng cung cấp cho khởi tạo tĩnh. constchỉ nói với trình biên dịch để không cho phép bất cứ ai sửa đổi nó. Biến này được đặt trong phân đoạn dữ liệu hoặc bss tùy thuộc vào kiến ​​trúc và có thể nằm trong bộ nhớ được đánh dấu chỉ đọc.

Tất cả đó là cách C xử lý các biến này (hoặc phương pháp C ++ xử lý các biến không gian tên). Trong C ++, một thành viên được đánh dấu staticđược chia sẻ bởi tất cả các phiên bản của một lớp nhất định. Cho dù đó là riêng tư hay không không ảnh hưởng đến thực tế là một biến được chia sẻ bởi nhiều trường hợp. Có consttrên đó sẽ cảnh báo bạn nếu có bất kỳ mã nào sẽ tìm mọi cách sửa đổi điều đó.

Nếu nó hoàn toàn riêng tư, thì mỗi phiên bản của lớp sẽ có phiên bản riêng (mặc dù trình tối ưu hóa).

+ Rất nhiều người đã đưa ra câu trả lời cơ bản nhưng không ai chỉ ra rằng trong C ++ constmặc định staticở namespace cấp độ (và một số đã cung cấp thông tin sai). Xem phần tiêu chuẩn C ++ 98 3.5.3.

Đầu tiên một số nền tảng:

Đơn vị dịch: Một tệp nguồn sau bộ xử lý trước (đệ quy) bao gồm tất cả các tệp bao gồm.

Liên kết tĩnh: Một biểu tượng chỉ có sẵn trong đơn vị dịch thuật của nó.

Liên kết ngoài: Một biểu tượng có sẵn từ các đơn vị dịch thuật khác.

– Ở cấp độ chức năng

staticcó nghĩa là giá trị được duy trì giữa các lệnh gọi hàm.
Các ngữ nghĩa của các staticbiến chức năng tương tự như các biến toàn cục ở chỗ chúng nằm trong phân đoạn dữ liệu của chương trình (chứ không phải ngăn xếp hoặc heap), xem câu hỏi này để biết thêm chi tiết về statictuổi thọ của biến.

– Ở classcấp độ

staticcó nghĩa là giá trị được chia sẻ giữa tất cả các thể hiện của lớp và constcó nghĩa là nó không thay đổi.

Const Static' Có Nghĩa Là Gì Trong C Và C ++
Const Static’ Có Nghĩa Là Gì Trong C Và C ++

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

Biến static (static variables)

Biến static được tạo ra bên trong một khối lệnh có khả năng lưu giữ giá trị của nó cho dù chương trình đã chạy ra bên ngoài khối lệnh chứa nó.

Biến static chỉ cần được khai báo một lần duy nhất, và tiếp tục được duy trì sự tồn tại xuyên suốt cho đến khi chương trình kết thúc.

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 <iostream>
 
void incrementAndPrint()
{
    int value = 1; // automatic duration by default
    ++value;
    std::cout << value << '\n';
} // value is destroyed here
 
int main()
{
    incrementAndPrint();
    incrementAndPrint();
    incrementAndPrint();
    
    return 0;
}

Mỗi khi hàm incrementAndPrint được gọi, một biến có tên gọi “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 đơn vị, giá trị in ra màn hình là 2. Khi hàm incrementAndPrint thực hiện xong tác vụ, biến “value” bị hủy. Cứ thực hiện liên tiếp như vậy, kết quả in ra màn hình là:

2
2
2

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

#include <iostream>
 
void incrementAndPrint()
{
    static int s_value = 1; // static duration variable
    ++s_value;
    std::cout << s_value << '\n';
} // s_value is not destroyed here, but became inaccessible
 
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” được tăng thêm 1, và còn được lưu giữ lại đó cho đến khi chương trình kết thúc. Kết quả in ra như sau:

2
3
4

Hàm static (static functions)

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

#include <iostream>

struct Test
{
   static void foo()
   {
      std::cout << "Called static function: foo" << std::endl;
   }
};

int main()
{
   Test::foo();
   return 0;
}

Các bạn có thể thấy, hàm foo được gọi mà không cần tạo ra thực thể kiểu Test.

Điểm đáng lưu ý trong việc sử dụng hàm static trong struct/class là chúng không thể truy xuất đến non-static members trong struct/class đó:

struct Test
{
   int value;

   void nonstatic_foo()
   {
   }

   static void foo()
   {
      value = 1; // error
      nonstatic_foo(); // error
   }
};
Bài Tập C++ OOP Giá Trị Của Biến Static
Bài Tập C++ OOP Giá Trị Của Biến Static

Bài viết liên quan

Leave a Reply

Your email address will not be published. Required fields are marked *

Hotline: 0984.876.750
Chat Facebook
Gọi điện ngay