Raii, Рimpl. Идиомы программирования

Содержание

Слайд 2

ИДИОМА RAII — ЗАХВАТ РЕСУРСА ЕСТЬ ИНИЦИАЛИЗАЦИЯ Идиома очень простая и

ИДИОМА RAII — ЗАХВАТ РЕСУРСА ЕСТЬ ИНИЦИАЛИЗАЦИЯ

Идиома очень простая и кратко

описывается следующим образом: в конструкторе объект получает доступ к какому либо ресурсу и сохраняет описатель ресурса в закрытый член класса, а при вызове деструктура этот ресурс освобождается. При объявлении объекта данного класса на стеке происходит и его инициализация с вызовом конструктора, захватывающий ресурс. При выходе из области видимости объект выталкивается из стека, но перед этим вызывается деструктор объекта, который и освобождает захваченный ресурс.
Слайд 3

class TelephoneLine { public: void pickUpThePhoneUp() { std::cout } void putThePhoneDown() { std::cout } };

class TelephoneLine
{
public:
  void pickUpThePhoneUp()
  { 
     std::cout << "Line locked\n";
  }
  void putThePhoneDown()
  {
     std::cout << "Line

unlocked\n";
  }
};
Слайд 4

class TelephoneCall { public: TelephoneCall() { telephoneLine = new TelephoneLine(); telephoneLine->pickUpThePhoneUp();

class TelephoneCall
{
public:
  TelephoneCall()
  {
     telephoneLine = new TelephoneLine();
     telephoneLine->pickUpThePhoneUp(); 
  }
  ~TelephoneCall()
  {
     telephoneLine->putThePhoneDown();
     delete telephoneLine;
  }
private:
  TelephoneCall (const TelephoneCall &);
  TelephoneCall& operator=(const TelephoneCall

&);
  TelephoneLine * telephoneLine;
};
Слайд 5

int main() { { std::cout TelephoneCall call; std::cout } std::cout }

int main()
{
  {
     std::cout << "Let's make a call to a friend.\n";
    

TelephoneCall call;
     std::cout << "Oh, we've talked enough. I need to take a nap. Goodbye!\n";
  }
  std::cout << "Zzzzzz...";
}
Слайд 6

После запуска мы увидим следующий вывод: Let's make a call to

После запуска мы увидим следующий вывод: Let's make a call to

a friend. Line locked Oh, we've talked enough. I need to take a nap. Goodbye! Line unlocked Zzzzzz...
Слайд 7

PIMPL

PIMPL

Слайд 8

Допустим, нам необходимо написать кроссплатформенное сетевое приложение с использованием сокетов. Для

Допустим, нам необходимо написать кроссплатформенное сетевое приложение с использованием сокетов. Для

этого нам необходим класс GeneralSocket (“Видимый класс”), который будет инкапсулировать в себе детали реализации конкретной платформы (“Скрываемый класс”). Часто требуется скрыть детали реализации от пользователей или других разработчиков:
Слайд 9

Для того, что бы была возможность изменять реализацию скрываемого класса без

Для того, что бы была возможность изменять реализацию скрываемого класса без

перекомпиляции остального кода, так как закрытые члены хоть и недоступны извне никому, кроме функций-членов и друзей, но видимы всем, кто имеет доступ к определению класса. Изменение определения класса приводит к необходимости перекомпиляции всех пользователей класса
Для сокрытия имен из области видимости. Закрытые члены хоть и не могут быть вызваны кодом вне класса, тем не менее они участвуют в поиске имен и разрешении перегрузок
Для ускорения времени сборки, так как компилятору не нужно обрабатывать лишние определения закрытых типов 
Слайд 10

//GeneralSocket.h #include “UnixSocketImpl.h” Class GeneralSocket{ public: connect(); private: UnixSocketImpl socket; } //GeneralSocket.cxx GeneralSocket::connect(){ socket.connectImpl(); }

//GeneralSocket.h #include “UnixSocketImpl.h” Class GeneralSocket{ public:  connect(); private:  UnixSocketImpl socket; }

//GeneralSocket.cxx GeneralSocket::connect(){  socket.connectImpl(); }
Слайд 11

//GeneralSocket.h Class UnixSocketImpl; Class GeneralSocket { public: GeneralSocket(); void connect(); private:

//GeneralSocket.h Class UnixSocketImpl; Class GeneralSocket { public:  GeneralSocket();  void connect(); private:

 UnixSocketImpl * socket; }

//GeneralSocket.cxx #include “UnixSocketImpl.h” GeneralSocket::GeneralSocket() : socket (new UnixSocketImpl){} GeneralSocket::~GeneralSocket() {  delete socket;  socket = 0; } void GeneralSocket::connect() {  socket->connectImpl(); }