С++ для начинающих


Закрытые и открытые функции-члены


Функцию-член можно объявить в любой из секций public, private или protected тела класса. Где именно это следует делать? Открытая функция-член задает операцию, которая может понадобиться пользователю. Множество открытых функций-членов составляет интерфейс класса. Например, функции-члены home(), move() и get() класса Screen определяют операции, с помощью которых программа манипулирует объектами этого типа.

Поскольку мы прячем от пользователей внутреннее представление класса, объявляя его члены закрытыми, то для манипуляции объектами типа Screen необходимо предоставить открытые функции-члены. Такой прием – сокрытие информации – защищает написанный пользователем код от изменений во внутреннем представлении.

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

До сих пор мы встречались лишь с функциями, поддерживающими доступ к закрытым членам только для чтения. Ниже приведены две функции set(), позволяющие пользователю модифицировать объект Screen. Добавим их объявления в тело класса:

class Screen {

public:

   void set( const string &s );

   void set( char ch );

   // объявления других функций-членов не изменяются

};

Далее следуют определения функций:

void Screen::set( const string &s )

{ // писать в строку, начиная с текущей позиции курсора



   int space = remainingSpace();

   int len = s.size();

   if ( space < len ) {

      cerr << "Screen: warning: truncation: "

           << "space: " << space

           << "string length: " << len << endl;

      len = space;

   }

   _screen.replace( _cursor, len, s );

   _cursor += len - 1;

}

void Screen::set( char ch )

{

   if ( ch == '\0' )

      cerr << "Screen: warning: "

           << "null character (ignored).\n";


   else _screen[_cursor] = ch;

}

В реализации класса Screen мы предполагаем, что объект Screen не содержит двоичных нулей. По этой причине set() не позволяет записать на экран нуль.

Представленные до сих пор функции-члены были открытыми, их можно вызывать из любого места программы, а закрытые вызываются только из других функций-членов (или друзей) класса, но не из программы, обеспечивая поддержку другим операциям в реализации абстракции класса. Примером может служить функция-член remainingSpace класса Screen(), использованная в set(const string&).

class Screen {

public:

   // объявления других функций-членов не изменяются

private:

   inline int remainingSpace();

};

remainingSpace() сообщает, сколько места осталось на экране:

inline int Screen::remainingSpace()

{

   int sz = _width * _height;

   return ( sz - _cursor );

}

(Детально защищенные функции-члены будут рассмотрены в главе 17.)

Следующая программа предназначена для тестирования описанных к настоящему моменту функций-членов:

#include "Screen.h"

#include <iostream>

int main() {

   Screen sobj(3,3); // конструктор определен в разделе 13.3.4

   string init("abcdefghi");

   cout << "Screen Object ( "

        << sobj.height() << ", "

        << sobj.width() << " )\n\n";

   // Задать содержимое экрана

   string::size_type initpos = 0;

   for ( int ix = 1; ix <= sobj.width(); ++ix )

      for ( int iy = 1; iy <= sobj.height(); ++iy )

      {

         sobj.move( ix, iy );

         sobj.set( init[ initpos++ ] );

      }

      // Напечатать содержимое экрана

      for ( int ix = 1; ix <= sobj.width(); ++ix )

      {

         for ( int iy = 1; iy <= sobj.height(); ++iy )

            cout << sobj.get( ix, iy );

         cout << "\n";

      }

      return 0;

}

Откомпилировав и запустив эту программу, мы получим следующее:

Screen Object ( 3, 3 )

abc

def

ghi


Содержание раздела