kzhereb / knu-is-ooop2019

Materials for "Fundamentals of OOP" course
MIT License
3 stars 0 forks source link

T10.09. Що означає static в класах? Як з ним працювати? #9

Open WAG13 opened 4 years ago

i1red commented 4 years ago

static поля/методи прив'язані саме до класу, а не до його об'єктів. До них можна звернутися без створення об'єкта наступним чином:

class Example { public: static void uselessMethod(); ... }

Example::uselessMethod()

Популярними прикладами використання static є зберігання кількості об'єктів класу(можна використати для створення ID об'єкта або у smart pointer'ах), паттерн Singleton

solovdaria commented 4 years ago

Якщо ми створюємо змінну з модифікатором static, то така змінна буде спільною для всіх об'єктів. Якщо ми звернемось до якоїсь static змінної у одного об'єкта і змінимо її значення, то якщо ми потім звернемось до тої самої змінної у другого об'єкта, то побачимо, що її значення було змінено. Якщо клас містить змінні static, то вони мають бути додатково визначені поза класом. Також існують методи static, але в середині них можна використовувати лише static змінні і не можна використовувати покажчик this.

yanaskyrda commented 4 years ago

У всіх методів класу, які не оголошені з ключевим словом static неявно передається параметр this, тоді коли метод оголошений з static цей параметр this не передається. Саме тому такі методи не мають доступ до нестатичних полів об'єкту. Тобто якщо маємо такий клас:

class A {
    std::vector<std::string> data;
    static int objectsAmount;
public:
    static void increaseAmount () {
        objectsAmount++;
    }
   void addData (const std::string& newData) {
        data.push_back(newData);
    }
}

Але насправді в метод addData також передається this, тому ми звертаємось до поля цього об'єкту (data.push_back(newData) це те ж саме, що й this->data.push_back(newData)). А в метод increaseAmount такий вказівник не передається, тому він не має доступу до полів об'єкту.

Velly69 commented 4 years ago

Статичний член даних в класі оголошується з допомогою ключового слова static. Оскільки, це є статичний член даних, то потрібно його визначити (описати змінну) за межами класу. Доступ до цього статичного члена даних мають усі екземпляри (об’єкти) класу. Якщо в класі оголошено статичний член, то усі екземпляри (об’єкти) класу розділяють цей статичний член класу. Точніше кажучи, цей статичний член класу є спільним для усіх об’єктів цього класу. На відміну від автоматичних даних (даних без слова static), не може створюватись декількох копій статичних даних. Пам’ять для статичного члена даних виділяється на стадії компоновки тільки один раз в той момент, коли визначається статичний елемент.

Статичні методи не прив'язані до об'єкту, тому вони не мають вказівника this, адже цей вказівник завжди вказує на об'єкт, з яким працює метод, а статичні методи можуть не працювати через об'єкт, тому цей вказівник this і не потрібен. По-друге, статичні методи можут звертатися напряму до інших статичних членів(змінних або функцій), але не можуть до нестатичних членів. Це пов'язано з тим, що нестатичні члени належать до об'єкта класу, а статичні методі - ні.

TaisiiaFenz commented 4 years ago

Якщо поле даних класу описана з ключовим словом static, то значення цього поля буде однаковим для всіх об'єктів даного класу. Статичні дані класу корисні в тих випадках, коли необхідно, щоб всі об'єкти включали в себе будь-яке однакове значення. class example { private: static int count; // загальне поле для всіх об'єктів public: example() // збільшення на 1 при створенні об'єкта { count++; } int getСount() // повертає значення count { return count; } }; int example::count = 0; // визначення count int main() { example a1, a2, a3; // створення 3-ьох об'єктів // кожен об'єкт бачить одне і те ж значення cout << "Кількість об'єктів " << a1.getCount() << endl; cout << "Кількість об'єктів " << a2.getCount() << endl; cout << "Кількість об'єктів " << a3.getCount() << endl; return 0; } Результат буде: Кількість об'єктів 3 Кількість об'єктів 3 Кількість об'єктів 3 Якщо використовувати не статичне, а автоматичне поле count, то конструктор збільшував би на одиницю значення цього поля для кожного об'єкта та, і результат роботи програми виглядав би наступним чином: Кількість об'єктів 1 Кількість об'єктів 1 Кількість об'єктів 1

AntonHladkiy commented 4 years ago

static змінні спільні для всіх об'єктів класу і також додатково задаються поза класом, static функції класу хоч і задаються в класі фактично до нього не належать.

RostyslavMV commented 4 years ago

static змінні є спільними для усіх об'єктів класу, тобто існує фактично один екземпляр такої змінної, а не створюється нова в кожному об'єкті. Їх використовувати варто, якщо, наприклад, потрібен counter для створених об'єктів, в конструкторі класу задаємо інкремент для counter і робимо counter статичною змінною.

ilyakorenevskyi commented 4 years ago

static змінні це змінні закріпленні за классов, тобто вони спільні для всіх об'єктів, фактично існує единй екземпляр, можна використовувати не оголосивши об'єкту классу.

WAG13 commented 4 years ago

Якщо ми пишемо static перед полем класу у нас не виділяється окремо пам'ять для кожного значення цього поля в окремому об'єкті, адже воно буде спільним для всіх об'єктів класу. Якщо ми пишемо static перед методом, то це означає, що ми не будемо змінювати поля класу і тому до static полів або методів можна звернутися без створення об'єкта. Наприклад:

class A {
public:   
   static int counter;
   static void inc_counter () {
        counter++;
    }
//......
}
A::inc_counter();

тоді counter зміниться для усіх об'єктів класу А

Vladyslav-Samokryk commented 4 years ago

Статичні методи можуть використовуватися для роботи зі статичними змінними-членами класу. Для роботи з ними не потрібно створювати об'єкти класу.

Класи можуть бути «чисто статичні» (з усіма статичними змінними-членами і статичними методами). Однак такі класи, по суті, еквівалентні оголошенню функцій і змінних в глобальному контексті і цього слід уникати, якщо у вас немає на це вагомих причин.