Skip to content

CPP 03. Классы и объекты в CPP. Определение класса с помощью class, struct, union. Ограничение доступа к членам класса в CPP. Члены класса и объекта. Методы класса и объекта. Константные члены класса. Схемы наследования.

Dmitriy Pisarenko edited this page Sep 7, 2023 · 4 revisions

Определение класса с помощью class, struct, union

Класс – тип данных, представляющий совокупность атрибутов объекта (переменные члены класса) и возможных операций над этими объектами (методов класса). Описывается в заголовочных файлах.

Механизм описания класса:

  • struct
  • class
  • union – не может быть базовым классом, и не может быть производным (поэтому нет уровня доступа protected). Нужен только для совместимости с Си. Его использование нежелательно, т.к. нет контроля со стороны компилятора.

У struct по умолчанию уровень доступа для членов public, а у class – private. У union – public. В union нет уровня protected, так как union не может быть ни базовым классом, ни производным.

По умолчанию в структуре и объединении члены классов открыты, в классе закрыты, чем достигается принцип инкапсуляции (нет доступа к данным извне)

Другое отличие структуры от класса: схема наследования по умолчанию у класса private, а у структуры - public.

class <имя класса> [ : <список базовых классов>] {
private:  //доступ к данным есть только внутри самого класса
   int a;
protected:  //доступ есть внутри класса и во всех его наследниках
   int b;    
public:  //доступны для внешнего кода
   int f();
};  //класс заканчивается ; как и структура
     
//В библиотечных классах лучше располагать члены в обратном порядке (начиная с public)
//Классы описываются в заголовочных файлах .h. Методы же определяются в .cpp

Схемы наследования

3 схемы наследования:

  1. private (схема по умолчанию): все члены базового класса получают уровень доступа private, причём из унаследованного класса нет доступа к private полям базового класса.
  2. protected: члены базового класса public получают уровень доступа protected
  3. public: все члены базового класса наследуются со своим уровнем доступа.
class A
{
private:
    int a;
protected:
    int b;
public:
    int f();
};
class B: private A // public / protected
{
private:
    int c;
protected:
    int d;
public:
    int g(); // все члены базового класса получат уровень доступа private
};

Для того, чтобы восстановить уровень доступа можно написать:

public:
   using A::f;

image

Вариант с private: произошла полная подмена интерфейса (f()-> g())
Вариант с protected: интерфейс тоже полностью подменяется, но у производных классов есть доступ к полям базового класса (b и f() перешли в уровень protected, все остальное без изменений).
Вариант с public: все члены со своим доступом, произошло расширение интерфейса.

Нужна возможность подмены интерфейса при наследовании (чтобы модифицировать программу, не изменяя уже написанный код), а наследование private и protected такой возможности не дают.

Модификатор final запрещает наследование от этого класса.

Члены класса и объекта. Методы класса и объекта

Члены класса не относятся к конкретному объекту, они общие для всех объектов данного класса. Перед ними ставится ключевое слово static. Память под них не относится к объекту (при вызове sizeof они не будут учитываться).

Размещение полей класса публичными – плохой тон, поскольку это противоречит принципу инкапсуляции (скрывание реализации, предоставление пользователю только интерфейса для работы).

Поля:

  • Члены объекта
  • Члены класса (static)

Методы:

  • Методы объекта
  • Методы класса (static)
    class A
    private:
       int a;                // Член объекта
       const int ca;         // Константный член объекта
       static int sa;        // Член класса
       static const int sca; // Константный член класса
     
    public:
       int f();              // Метод объекта
       int f() const;         // Константный метод объекта
       static int sg();      // Метод класса
       A(int ia) :
        // Объект еще не создан
            a(ia),  // Так можно - объекта еще нет	 
            ca(ia), // Так можно - объекта еще нет
            sa(ia), // Ошибка - sa не член объекта
            csa(ia) // Ошибка - cas не член объекта
        {	
        // Объект создан 
            a = ia;   // Так можно
            ca = ia;  // Константу изменить нельзя - объект уже создан
            sa = ia;  // Так можно	
            csa = ia; // Константу изменить нельзя - объект уже создан
        }
    };
     
    // static поля класса можно проинициализировать здесь
    int A::sa = 0;
    const int A::csa = 0;

Константный метод объекта обязуется не изменять поля объекта.

Метод класса вызывается имя_класса::имя_метода. Метод объекта вызывается через сам объект. Методы объекта/класса имеют доступ ко всем элементам класса. Методы класса не получают this. Методы класса могут работать только со статическими членами.

Метод класса не может быть константным, т.к. не принимает указатель на объект (this)

    int A::f() // :: - оператор доступа к контексту
               // Используется для определения метода вне класса
    {
        return this->a; // this – ключевое слово объекта, его можно не писать
        // return a; - равносильно
    }
     
    int A::sg()
    {
        return sa;
    }
Clone this wiki locally