Menu
Coddy logo textTech

Члены экземпляра против статических

Часть раздела Объектно-ориентированное программирование путешествия по C++ на Coddy. Урок 27 из 104.

До сих пор каждая созданная тобой переменная-член принадлежит определённому объекту. Когда ты создаёшь два объекта Player, у каждого есть собственные name и health. Они называются членами экземпляра — они существуют отдельно для каждого экземпляра класса.

Но что, если вам нужны данные, общие для всех объектов? Например, отслеживать, сколько всего существует игроков.

Именно здесь на помощь приходят статические члены. Статический член принадлежит самому классу, а не какому-либо конкретному объекту.

class Player {
    std::string name;           // Член экземпляра — у каждого игрока свой
    int health;                 // Член экземпляра
    
    static int playerCount;     // Статический член — общий для ВСЕХ игроков
    
public:
    Player(std::string n) : name(n), health(100) {
        playerCount++;          // Увеличиваем при создании любого игрока
    }
    
    ~Player() {
        playerCount--;          // Уменьшаем при уничтожении любого игрока
    }
};

Ключевое различие: доступ к членам экземпляра осуществляется через объект, тогда как к статическим членам можно обращаться непосредственно по имени class. Считай, что члены экземпляра — это «по одному на объект», а статические члены — «по одному на class».

Члены экземпляраСтатические члены
Уникальны для каждого объектаОбщие для всех объектов
Создаются при создании объектаСуществуют до создания любого объекта
Доступны через объект: player.healthДоступны через класс: Player::playerCount

Статические члены полезны для счётчиков, значений конфигурации или любых данных, которые логически относятся к классу, а не к отдельным объектам.

challenge icon

Задание

Легко

Давайте создадим систему учёта товаров, которая отслеживает сведения как об отдельных товарах, так и об общей статистике инвентаря с использованием экземплярных и статических членов.

Вы создадите два файла, чтобы организовать код:

  • Product.h: Define класс Product, который управляет отдельными товарами и одновременно отслеживает данные по всему инвентарю. Ваш класс должен иметь:
    • Экземплярные члены: name (строка) и price (double): уникальные для каждого товара
    • Статический член totalProducts, который подсчитывает, сколько товаров существует current
    • Статический член totalValue, который отслеживает совокупную цену всех товаров
    • constructor, принимающий name и price, инициализирующий экземплярные члены и обновляющий оба статических счётчика (увеличить count, добавить price к общей стоимости)
    • destructor, который обновляет статические счётчики при удалении товара (уменьшить count, вычесть price из общей стоимости)
    • Метод getInfo(), возвращающий строку в формате: "<name>: $<price>"
    • Статический метод getInventoryStats(), возвращающий строку: "Products: <count>, Total Value: $<value>"
  • main.cpp: Продемонстрируйте, как статические члены являются общими для всех объектов, тогда как экземплярные члены остаются уникальными. Считайте из входных данных два названия товаров и их цены (name1, price1, name2, price2: каждое на отдельной строке), затем:
    • Выведите начальную статистику инвентаря, используя имя класса: Product::getInventoryStats()
    • Создайте блок области видимости с фигурными скобками и внутри него создайте Product с первым названием и ценой. Выведите сведения о нём и current статистику инвентаря.
    • After завершения блока (первый товар уничтожен) выведите "After first scope:", а затем статистику инвентаря
    • Создайте another Product со вторым названием и ценой. Выведите сведения о нём и статистику инвентаря.
    • Создайте третий Product с названием "Bonus" и ценой 5.00. Выведите итоговую статистику инвентаря.

Не забудьте определить статические члены вне класса в файле заголовка (после определения класса). Форматируйте цены с двумя десятичными знаками, используя std::fixed и std::setprecision(2) из <iomanip>.

Include файл заголовка в main.cpp с помощью #include "Product.h".

Попробуйте сами

#include <iostream>
#include <string>
#include "Product.h"

using namespace std;

int main() {
    // Прочитать ввод
    string name1;
    double price1;
    string name2;
    double price2;
    
    getline(cin, name1);
    cin >> price1;
    cin.ignore();
    getline(cin, name2);
    cin >> price2;
    
    // TODO: Вывести начальную статистику инвентаря с помощью Product::getInventoryStats()
    
    // TODO: Создать блок области видимости с фигурными скобками
    // Внутри блока:
    //   - Создать Product с name1 и price1
    //   - Вывести его информацию с помощью getInfo()
    //   - Вывести текущую статистику инвентаря
    
    // TODO: After the block ends, print "After first scope:"
    // Затем вывести статистику инвентаря
    
    // TODO: Создать ещё один Product с name2 и price2
    // Вывести его информацию и статистику инвентаря
    
    // TODO: Создать третий Product с именем "Bonus" и ценой 5.00
    // Вывести итоговую статистику инвентаря
    
    return 0;
}
quiz iconПроверьте себя

В этом уроке есть небольшой тест. Начните урок, чтобы ответить на вопросы и сохранить прогресс.

Все уроки раздела Объектно-ориентированное программирование

Потренируйтесь самостоятельно: Онлайн-компилятор C++