Меню сайта

Урок 22. Частные и общие данные в C++


СОКРЫТИЕ ИНФОРМАЦИИ

Как вы уже знаете, класс содержит данные и методы (функции). Для использования класса программы просто должны знать информацию, которую хранит класс (его элементы данных) и методы, которые манипулируют данными (функции). Вашим программам не требуется знать, как работают методы. Более того, программы должны знать только, какую задачу выполняют методы. Например, предположим, что у вас есть класс file. В идеале ваши программы должны знать только то, что этот класс обеспечивает методы file.print, который печатает отформатированную копию текущего файла, или file.delete, который удаляет файл. Вашей программе не требуется знать, как эти два метода работают. Другими словами, программа должна рассматривать класс как «черный ящик». Программа знает, какие методы необходимо вызвать и какие параметры им передать, но программа ничего не знает о рельной работе, выполняющейся внутри класса (в «черном ящике»).

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

class employee

{ —
public:
— — -char name [64]-
— — -long employee_id-
— — -float salary-
— — -void show_employee(void)-
}

При создании класса вы могли бы иметь элементы, чьи значения используются только внутри класса, но обращаться к которым самой программе нет необходимости. Такие элементы являются частными (private), и их следует скрывать от программы. Если вы не используете метку public, то по умолчанию C++ подразумевает, что все элементы класса являются частными. Ваши программы не могут обращаться к частным элементам класса, используя оператор точку. К частным элементам класса могут обращаться только элементы самого класса. При создании класса вам следует разделить элементы на частные и общие, как показано ниже:

class some_class

{ —
public:
— — -int some_variable-
— — -void initialize_private(int, float)- —//———&gt- Общие элементы
— — -void show_data(void)-
private:
— — -int key_value- —//—————————————&gt- Частные элементы
— — -float key_number-
}

Как видите, меткиpublic и private легко позволяют определять, какие элементы являются частными, а какие общими. В данном случае программа может использовать оператор точку для обращения к общим элементам, как показано ниже:

some_class object- // Создать объект —
object.some_variable = 1001-
object.initialize_private(2002, 1.2345)-
object.show_data()

Если ваша программа пытается обратиться к частным элементамkey_value илиkey_number, используя точку, компилятор сообщает о синтаксических ошибках.

Как правило, вы будете защищать элементы класса от прямого доступа к ним делая их частными. При этом программы не могут непосредственно присваивать значения таким элементам, используя оператор точку. Вместо того чтобы присвоить значение, программа должна вызвать метод класса. Предотвращая прямой доступ к элементам данных, вы, таким образом, можете гарантировать, что им всегда будут присваиваться допустимые значения. Например, предположим что объектnuclear_reactor вашей программы использует переменную с именем melt_down, которая всегда должна содержать значение в диапазоне от 1 до 5. Если элементmelt_down является общим, программа может непосредственно обратиться к элементу, изменяя его значение произвольным образом:

nuclear_reactor.melt_down = 101

Если вместо этого вы делаете переменную частной, то можете использовать метод класса, напримерassign_meltdown, чтобы присвоить значение этой переменной. Как показано ниже, функцияassign_meltdown может проверять присваиваемое значение, чтобы убедиться, что оно является допустимым:

int nuke::assign_meltdown(int value)

{
— — -if ((value &gt- 0) &amp-&amp- (value &lt-= 5))

— — -{
— — — — — -melt_down = value-
— — — — — -return(0)- // Успешное присваивание —
— — -} else
-return(-1)- // Недопустимое значение —
}

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

Общие и частные элементы

Классы C++ содержат данные и элементы. Чтобы указать, к каким элементам классов ваши программы могут обращаться напрямую, используя оператор точку, C++ позволяет вам определять элементы класса как общие{public) и частные(private). Таким образом, ваши программы могут непосредственно обращаться к любым общим элементам класса, используя оператор точку. С другой стороны, к частным элементам можно обратиться только через методы класса. Как правило, вы должны защищать большинство элементов данных класса, объявляя их частными. Следовательно, единственным способом, с помошью которого ваши программы могут присвоить значение элементам данных, является использование функцийкласса, которые способны проверить и скорректировать присваиваемые значения.

ИСПОЛЬЗОВАНИЕ ОБЩИХ И ЧАСТНЫХ ЭЛЕМЕНТОВ КЛАССА

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

class employee

{ —
public:
— — -int assign_values(char *, long, float)-
— — -void show_employee(void)-
— — -int change_salary(float)-
< font face="Times New Roman, Times, serif"> — — -long get_id(void)-
private:
— — -char name [64] —
— — -long employee_id-
— — -float salary-
}

Как видите, класс защищает все свои элементы данных, объявляя их частными. Для доступа к элементам данных программа должна использовать интерфейсные функции. Ниже приведена реализация программы INFOHIDE.CPP:

#include &lt-iostream.h&gt-

#include &lt-string.h&gt-

class employee

{
public:
— — -int assign_values(char *, long, float)-
— — -void show_employee(void)-
— — -int change_salary(float)-
— — -long get_id(void)-
private:
— — -char name [64]-
— — -long employee_id-
— — -float salary-
)-

int employee::assign_values(char *emp_name, —long emp_id, float emp_salary)

{
— — -strcpy(name, emp_name)-
— — -employee_id = emp_id-
— — -if (emp_salary &lt- 50000.0)

— — -{
— — — — — -salary = emp_salary-
— — — — — -return(0)- // Успешно —
— — — -}
— — else
return(-1)- // Недопустимый оклад }

void employee::show_employee(void)

{
— — -cout &lt-&lt- «Служащий:» &lt-&lt- name &lt-&lt- endl-
— — -cout &lt-&lt- «Номер служащего: «&lt-&lt- employee_id &lt-&lt- endl-
— — -cout &lt-&lt- «Оклад:» &lt-&lt- salary &lt-&lt- endl-
}

int employee::change_salary(float new_salary)

{
— — -if (new_salary &lt- 50000.0)

— — -{
— — — — — -salary = new_salary-
— — — — — -return(0)- // Успешно } else —return(-1)- // Недопустимый оклад }

long employee::get_id(void)

{
— — -return(employee_id) —
}

void main(void)

{
— — -employee worker-

— — -if (worker.assign_values(«Happy Jamsa», 101, 10101.0) == 0)

— — -{
— — — — — -cout &lt-&lt- «Служащему назначены следующие значения»&lt-&lt- endl-}
— — — — — -worker.show_employee()-
— — — — — -if (worker.change_salary(35000.00) == 0)

— — — — — -{
— — — — — — — — -cout &lt-&lt- «Назначен новый оклад»&lt-&lt- endl-
— — — — — — — — -worker.show_employee()-
— — — — — -} —
— — -} —
— — -else
— — -cout &lt-&lt- «Указан недопустимый оклад»&lt-&lt- endl-
}

Выберите время, чтобы исследовать операторы программы более подробно. Несмотря на то что программа достаточно длинна, ее функции на самом деле очень просты. Методassign_values инициализирует частные данные класса. Метод использует операторif, чтобы убедиться, что присваивается допустимый оклад. Методshow_employee в данном случае выводит частные элементы данных. Методыchange_salary иget_id представляют собой интерфейсные функции, обеспечивающие программе доступ кчастным данным. После успешной компиляции и запуска этой программы отредактируйте ее и попытайтесь обратиться напрямую к частным элементам данных, используя оператор точку внутриmain. Так как вы не можете напрямую обратиться к частным элементам, компилятор сообщит о синтаксических ошибках.

Что такое интерфейсные функции

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


ИСПОЛЬЗОВАНИЕ ОПЕРАТОРА ГЛОБАЛЬНОГО РАЗРЕШЕНИЯ ДЛЯ ЭЛЕМЕНТОВ КЛАССА

Если вы рассмотрите функции в программе INFOHIDE.CPP, вы обнаружите, что имена параметров функции часто предваряются символами етр_, как показано ниже:

int employee::assign_values(char *emp_name, long emp_id, float emp_salary)

Символы етр_ использовались, чтобы избежать конфликта между именами параметров и именами элементов класса. Если подобный конфликт имен всe же происходит, вы можете разрешить его, предваряя имена элементов класса именем класса и оператором глобального разрешения (::). Следующая функция использует оператор глобального разрешения и имя класса перед именем элементов класса. Исходя из этого, любой читающий эти операторы поймет, какие имена соответствуют классуemployee:

int employee::assign_values(char *name, —long employee_id, float salary)

{
— — -strcpy(employee::name, name) —
— — -employee::employee_id = employee_id-
— — -if (salary &lt- 50000.0)

{
— — — — — -employee::salary = salary-

— — -return(0)- // Успешно } else
— — -return(-1)- // Недопустимый оклад —
}

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

Использование оператора глобального разрешения для указания элементов класса

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


class_naine: :member_name = some_value-

ЧАСТНЫЕ ЭЛЕМЕНТЫ КЛАССА НЕ ВСЕГДА ЯВЛЯЮТСЯ ДАННЫМИ

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


ЧТО ВАМ НЕОБХОДИМО ЗНАТЬ

Управляя доступом программы к элементам класса, вы снижаете возможность ошибок, которые происходят в результате злоупотребления этими элементами. Чтобы управлять доступом к элементам класса, можно использовать частные элементы. Большинство определений классов C++, которые вы встретите, будут использовать сочетание частных и общих элементов. Одна из наиболее широко используемых операций, которую ваши программы выполняют при создании объекта, представляет собой инициализацию элементов данных объекта. Из урока 23 вы узнаете, что C++ позволяет вам определять специальную функцию, называемую конструктором, которая автоматически вызывается каждый раз при создании объекта. Используя конструктор, ваша программа легко может инициализировать элементы класса. До изучения урока 23 убедитесь, что освоили следующие основные концепции:

    1. Элементы класса могут быть общими или частными. Программы могут напрямую обращаться к общим элементам, используя оператор точку. С другой стороны, к частным элементам можно обращаться, используя только методы класса.
    2. Если это не оговорено явно, C++ считает все элементы частными.
    3. Программы присваивают значения и обращаются к частным элементам, используя интерфейсные функции.
    4. При создании программы, манипулирующей элементами класса, вы можете предварять имя каждого элемента именем класса и оператором глобального разрешения (::), напримерemployее::name, для избежания возможных конфликтов имен.

Категория: Обучение C++ | Дата: 01.04.13

Меню раздела
Блок