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




int number;

double temperature;

char day;

}; // Описание заканчивается точкой с запятой!!!

Вместо термина «Имя структуры» иногда используется термин дескриптор структуры.

Обращение к члену структуры производится с указанием через точку имени структуры и имени элемента:

Имя_структуры.Имя_члена_структуры

Понятие структура значительно шире, чем понятие массива. На самом деле, каждый раз объявляя структуру, мы создаем новый тип, который, далее объявляется в программе.

 

#include<iostream.h>

#include<windows.h>

struct book{

char name[10];

int page;

float price;

};

Int main(void)

{

SetConsoleCP(1251);

SetConsoleOutputCP(1251);

book b1;

cout<<"Название книги: ";

cin>>b1.name;

cout<<"Цена: ";

cin>>b1.price;

cout<<"число страниц: ";

cin>>b1.page;

cout<<b1.name<<endl<<b1.price<<endl<<b1.page;

char z;

cin>>z;

return 0;

}

Можно создать массив из струтур

 

#include<iostream.h>

#include<windows.h>

struct book{

char name[10];

int page;

float price;

};

main(){

book b[3];

SetConsoleCP(1251);

SetConsoleOutputCP(1251);

for(int i=0;i<3;i++){

cout<<"Фамилия автора: ";

cin>>b[i].name;

}

SetConsoleOutputCP(1251);

for(int i=0;i<3;i++){

cout<<"Имеются книги следующих автров: " <<b[i].name<<endl;;

}

char z;

cin>>z;

}

 

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

 

#include <iostream>

#include <cmath> //подключение библиотеки арифметических функций

using namespace std;

//------------------------------------------

struct account{ //объявление о создании структурного типа

// далее идет описание структуры

double beginSum; //начальная сумма

double procentStavka; //процентная ставка

int numberPeriod; //число переодов начисления процентов

}; //описание заканчивается точкой с запятой

//------------------------------------------

//Главная функция программы

int main(){

account bank; //объявление экземпляра структуры bank,

// типа account

double summa=0, incom=0; /* при объявлении переменные

можно инициализировать */

char work='y';

while(work=='y'||work=='Y'){

cout<<"\nInput benining summ ";

cin>> bank.beginSum; //обращение к элементу структуры

cout<<"\nInput % stav ";

cin>>bank.procentStavka; //обращение к элементу структуры

cout<<"\nInput numbers period ";

cin>>bank.numberPeriod; //обращение к элементу структуры

summa=bank.beginSum*pow((1+

bank.procentStavka/(100*bank.numberPeriod)),

bank.numberPeriod);

cout<<"\nsumma="<<summa; //Сумма с накопленными процентами

incom=summa-bank.beginSum; //Доход

cout<<"\nincom="<<incom;

cout<<"\n\nContinue? ";

cin>>work;

}

return 0;

}

 

Как всегда, для С++ действует правило – переменная должна быть описана до первого обращения к ней. В данном случае описание структуры вынесено перед функцией main, хотя описание структуры можно выполнтить внутри функции main. Попробуйте это сделать самостоятельно.

Следует еще обратить внимание, что имя структуры это не объект (т.е. не исполняемая программа), а только тип, по образцу которого строятся подобные друг другу объекы.

Определение структурного типа может быть совмещено с объявлением конкретной структуры этого типа, например

 

struct strc {int name1; doubl name2; char name3;} A, B, C;

То есть имена объектов структурного типа следует записать сразу после объявления структуры.

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

 

//Структура с функцией

#include <iostream>

using namespace std;

struct book{ //описание структуры

char name[50]; //Наименование

int page; //Количество страни ц

double price; //Цена

void print(); /*Внимание, записывается только прототип функции */

}; //обязательно точка с запятой

// описание функции

/* при описании нужно указывать к какой структуре принадлежит

* функция, что делается с помощью оператора:: */

void book::print(){

cout<<endl<<"Name"<<name<<endl<<"page="<<page<<endl

<<"price="<<price;

} //конец описания функции

//=========================================================

main(){

book volume;

cout<<"\nName of the book ";

char sign;

for(int i=0;i<50;i++){

cin>>volume.name[i]; //вводится как строка

if (volume.name[i]=='*') break;

}

cout<<"\nNumber pages=";

cin>>volume.page;

cout<<"\nPrice=";

cin>>volume.price;

cout<<"PRINT? \"y\" or \"n\"";

cin>> sign;

if(sign=='y'||sign=='Y')volume.print();

else cout<<"\n\n The end";

}

После компиляции программа запросит название книги Name of the book. Введите произвольный набор символов, после чего введите символ ‘*’ и нажмите ввод. Далее программа запросит число число страниц Number pages и цену Price. Числа тоже могут быть произвольными.

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

Использование указателей в структурах

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

struct date { char *name1; // фамилия

char *name2; // имя

char *name3; // отчество

int yearBorn; //год рождения

float middleGrade; // средний балл

};

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

имя_структурного_типа *имя_указателя_на_структуру;

Например, после объявления структурного типа date можно объявить структуру

date student1;

date *point1=& student1;

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

#include <iostream>

#include <windows.h>

using namespace std;

struct date { // объявление структурного типа // ôàìèëèÿ

char *name1;

char *name2; // èìÿ

char *name3; // îò÷åñòâî

int yearBorn; //ãîä ðîæäåíèÿ

float middleGrade; // ñðåäíèé áàëë

};

//------------------------------------------------

void main(){ SetConsoleOutputCP(1251);

date student1;

date *point1=&student1; //объявление указателя на структуру

point1->name1="Иванов"; /*операция доступа к элементу структуры*/

cout<<student1.name1<<endl;

}

 

4.1. Демонстрационные программы

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

 

struct ffblk {

long ff_reserved;

long ff_fsize; /* file size */

unsigned long ff_attrib; /* attribute found */

unsigned short ff_ftime; /* file time */

unsigned short ff_fdate; /* file date */

char ff_name[256]; /* found file name */

}

 

В программе также будут использованы две функции- findfirst и findnext из библиотеки dir. Кстати, эти функции обычно используются в паре.

Прототипы функций имеют следующий вид:

int findfirst(const char *pathname, struct ffblk *ffblk, int attrib);

int findnext(struct ffblk *ffblk);

Функция findfirst предназначена для поиска файла с указанным шаблоном из указанной директории. Например, C:\TEST\myfail.*. Если поиск оказался успешным, то возвращаемое значение равно 0. Когда файлов с указанным именем нет, то возвращается -1. Результаты поиска записываются в рассмотренную ранее структуру.

Функция findnext использует заполненную структуру и ищет следующий еще не найденный обеими функциями файл удовлетворяющий указанным требованиям. Если такой файл найден, то возвращается 0. Если такой файл отсутствует или список исчерпан, возвращается -1.

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

Теперь рассмотрим немного измененный пример программы из раздела Help «Borland C++6». Программа выводит список файлов каталога по заданному шаблону.

 

#include <dir>

#include <dos>

#include <iostream>

using namespace std;

Int main(void)

{

struct ffblk ff;// структура, определенная в библиотеке dos

int done;/* переменная, которая информирует о конце списка файлов */

cout<<"Directory listing of *.*\n";

done = findfirst("*.*",&ff,0);//функция из dir

while (!done) /* здесь используются логические переменные

в стиле С */

{

cout<< ff.ff_name<<" "<<ff.ff_fsize<<"\n";

done = findnext(&ff);

}

return 0;

}

 

 

6. Объединения

В языке С++ используются типы довольно похожие на структуры. Эти типы называются объединения. Можно сказать, что объединение это частный случай структуры. Формат описания точно такой же, но вместо слова struct используется union.

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

Рассмотрим пример в котором нужно указать способ оплаты - картой или чеком.

#include<iostream.h>

#include<windows>

void main(){

enum paytype{CARD,CHECK};

paytype type;

union payment{

char card[25];//Имя карты

long check;} //Номер чека

info;//Обявление переменной типа объединение

type=CARD;

SetConsoleOutputCP(1251);

cout<<"Введите ifo.card:";

cin.getline(info.card,25);

cout<<"Введите info.check:";

cin>>info.check;

switch(type){

case CARD: cout<<info.card<<endl;break;

case CHECK: cout<<info.check<<endl;break;

}

char z;

cin>>z;

}

Вот результат

Полученное значение 90 говорит о том, что результат обращения к элементу объединения не определен. Кстати, 90 это не код ошибки. Просто это случайное число. Вместо него могут быть какие-то символы.

/////////////////////////////////////////////////////////////

#include<iostream.h>

#include<windows>

void main(){

enum paytype{CARD,CHECK};

paytype type;

union payment{

char card[25];//Имя карты

long check;} //Номер чека

info;//Обявление переменной типа объединение

type=CARD;

SetConsoleOutputCP(1251);

cout<<"Введите info.check:";

cin>>info.check; /*В данном случае происходит обращение к элементу, который был последним размещен в памяти*/

cout<<"Введите ifo.card:";

cin.getline(info.card,25);

switch(type){

case CARD: cout<<info.card<<endl;break;

case CHECK: cout<<info.check<<endl;break;

}

char z;

cin>>z;

}

 

 

7. Объектно-ориентированное программирование

 

Программирование в том виде, в котором мы его описали, принято называть процедурным программированием. Название объясняется тем, что во многих языках функция называется процедурой. Вершиной такого рода программирования явилось применение функций (процедур). В начале 90-х годов стала внедряться идея так называемого объектно-ориентированного программирования (ООП). Это позволило использовать созданные ранее программы как типы данных, осуществлять наследование свойств. Об этом и многом другом мы расскажем в этой главе.

Нужно отметить, что превосходство ООП заметно только при разработке достаточно больших и сложных программ, поэтому все достоинства такого подхода в рассмотренных ниже примерах далеко не очевидны. Больше того ООП, как правило, неэффективно применительно к небольшим программам.

 

7.1. Классы и объекты

Когда мы впервые знакомились с программами, то сказали, что программа на С++ начинается с функции main(), затем уточнили, что на самом деле программа начинается с директив препроцессора. Но и это не совсем верно. Есть программы, которые начинаются со слова class. Да и называются такие программы классами. Сразу возникает вопрос – зачем нужны какие то классы? Ответить на этот вопрос пока не так просто. Но все же кое-что сказать можно.

Редактируя документы в известной программе "MS Word" каждый раз, создавая чистое окно, вы заставляете компьютер создавать новую программу. Компьютер не обладает творческими способностями, и может создавать новые программы, используя определенные ранее прототипы или, лучше сказать, шаблоны. Вот они и есть классы. Кроме понятия класс нам потребуется связанное с ним понятие - объект класса, или просто объект.

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

Представим себе, что имеются чертежи, а лучше сказать техническая документация по производству автомобиля, пусть это будет ВАЗ2110. Здесь слово ВАЗ2110 на самом деле является именем марки. Вместо слов марка мы применим слово класс, т.е ВАЗ 2110 это имя класса. По чертежам на автозаводе изготавливаются автомашины. Рассмотрим идеальный случай, когда по одним и тем же чертежам изготавливаются совершенно одинаковые автомобили. Каждый автомобиль представляет собой самостоятельный объект. Эти объекты нужно как-то различать, хотя бы для того, чтобы вести учет выпускаемой продукции. С этой, а также с некоторыми другими целями, каждому объекту присваивается идентификационный номер или VIN (verification identification namber). На самом деле, на автомобиле есть еще несколько номеров, но сейчас мы о них забудем. Идентификационный номер, по существу, является именем автомобиля, именно он участвует во всех документах, сопровождающих автомобиль. Созданные совершенно одинаковые автомобили поступают в продажу, заправленные разным количеством бензина и проехав разное расстояние. Тогда для покупателя эти автомобили будут отличаться начальной заправкой, начальным пробегом или, говоря иначе, начальными условиями. Покупатель использует объект в соответствии со своими потребностями, не интересуясь чертежами автомобиля, марками сталей и пластмасс, техническими условиями и ГОСТами, поставщиками комплектующих изделий и т.п. Более того, покупатель часто даже не знает, как устроен автомобиль, но это не мешает использовать его по своему назначению.

Аналогичным образом дело обстоит в программировании. Мы можем написать программу, которая в дальнейшем будет пригодна для использования в наших задачах. Этой программе присвоим имя, и поместим её в память компьютера. В дальнейшем будем называть такую программу классом. Это наши чертежи. Если по образу этой программы мы создадим новую программу со своим именем (VIN-ом) и в ней дадим переменным конкретные значения (начальный пробег), то такую новую программу будем называть объектом, - это экземпляр автомобиля. В дальнейшем можно пользоваться этим объектом, не обращаясь к самому классу. Таких экземпляров может быть много, но они должны отличаться именем. Подчеркнем еще раз, что в нашем распоряжении должны быть, по крайней мере, две программы, одна из них класс, его создает программист, другая - объект создается компилятором на основании этого класса.

Формальное определение классов и объектов мы дадим позднее, а сейчас попробуем создать какой-нибудь класс и получить объекты. Делается это довольно просто, что видно из следующего примера.

Создадим программу которая определяет количество дней в году по номеру года (високосный год содержит 366 дней), и оформим её в виде класса.

#include <iostream> //директивы остаются без изменения

using namespace std;

class clYear //программа начинается со слова class

// за которым следует имя класса

{ //далее идет тело класса

public: //зарезервированное слово, которое означает

//доступность членов класса

int days(int); //прототип функции которая будет описана позднее

} // Внимание! класс заканчивается точкой с запятой

 

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

Теперь запишем самостоятельную программу. Как обычно, она начинается с функции main(), в которой совершим на первый взгляд совершенно необычное действие - объявим класс (программу) clYear как тип данных.

int main(){

clYear obYear; //Объявление объекта obYear в виде

//переменной типа clYear

int numberYear=2000; //переменная, которая означает номер года

while(numberYear>0){ //далее предлагается ввести номер года

cout<<"\n Input number year ";

cin>> numberYear;

cout<<"The "<<numberYear<<" consist "

<<obYear.days(numberYear) // функция класса вызывается через

// имя объекта и имя функции

// разделенных точкой

<<" days";

}

}

 

Дадим, наконец, описание самой функции, которая определяет количество дней в году.

int clYear::days(int n){ /*при описании функции указывается

возвращаемый тип имя класса

к которому принадлежит функция

двойное двоеточие, имя функции */

if(n%4==0) return 366; //деление нацело определяет

//високосный год

else return 365;

}

Описание функции можно переместить, поставив его перед функцией main.

Теперь обсудим результаты.

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

Class имя

{

тело класса

};

2. В классе содержатся только прототипы функций. Сами функции описываются вне класса. Инициализация в описании класса запрещена.

3. В основной программе создается новая переменная, тип которой соответствует имени класса, подобно тому, как это делается для переменных базовых типов.

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

Рассматривая этот пример, мы немного слукавили. Лукавство состоит в том, что класс, его метод и основная часть программы при компиляции сохраняются в одном файле. То есть мы показали только то, что главная функция main() успешно работает с классом, если тот хранится в том же файле. Но на самом деле мы обещали более мощные возможности. Вспомним, мы говорили о том, что класс может храниться где-то в другом месте вне файла программы, а мы можем воспользоваться классом для создания объекта. Не спешите, у нас еще будет возможность поговорить об этом, когда мы будем рассказывать о, так называемых, модулях. А сейчас продолжим рассказ о классах и объектах.

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

Из приведенного примера непонятно зачем нужно было создавать класс, когда все гораздо проще можно было сделать без него. Но цель примера состояла в том, чтобы показать, как создать класс. Вот более сложный пример:

#include<iostream.h>

#include<string.h>

class Book{ /*Обратите внимание: код класса представляет собой

схематическое опиание некоторого шаблона по которому

будут строиться объекты */

public:

//переменные класса

char title[256];

char author[64];

float price1;

int number;

//функции или методы класса

void show_book(); //вывод информации об авторе и названии

float get_price(); //расчет стоимости партии

};

//---------------------------

void main(){

Book b1, b2; // создаются два объекта класса Book

//задаем параметры первого объекта

strcpy(b1.title, "War and pice");

strcpy(b1.author, "Tolstoy");

b1.price1=1000; // обращение к члену объекта через оператор точка

b1.number=10;

//задаем параметры второго объекта

strcpy(b2.title, "C++");

strcpy(b2.author, "Straustrup");

b2.price1=500;

b2.number=20;

//

b1.show_book();

b2.show_book();

cout<< "\nbalans="<<b1.get_price()+b2.get_price();

char z;

cin>>z;

}

//описание функций класса

void Book::show_book(){cout<<author<<": "<<title<<endl;}

float Book::get_price(){return price1*number;}

Вот результат:

 

Еще раз обратите внимание на то, что код класса это скелет, который описывает основу класса. В нем можно делать только объявления переменных и прототипов функций. Инициализировать переменные, или описывать функции нельзя. Функции описываются вне класса. Причем их описание может быть как до опиания кода класса, так и после кода класса. Возникает вопрос: как же инициализировать переменные класса? Ответ очень простой: для этого каждый класс имеет специальную функцию, которая называется конструктором. Конструктор специфическая функция. Она не возвращает никакого значения, т.е перед ее именем не нужно ничего писать, даже void. Ее имя совпадает с именем класса. Если такая функция не написана программистом она создается автоматически компилятором С++. Именно так компилятор поступил в рассмотренном примере. О конструкторах мы будем говорить чуть позже.

Сейчас обратимся к непонятной пока метке public:. На самом деле это не метка, а, так называемый, спецификатор, иначе говоря, зарезервированное слово, которое означает, что все члены класса стоящие после него являются доступными (публичными), т.е. к ним можно обращаться из других классов, или из функции main. Под словом обращаться, здесь подразумевается следующее: если это переменная, то ее значение может быль прочитано и/или изменено, если это метод, то он может быть вызван.

Возникает вопрос: если есть открытые члены класса, то, вероятно, есть и закрытые, Действительно это так. Закрытые члены класса отделяются специификаатором «private:». Доступ к закрытым членам класса ограничен. В частности к ним могут обращаться только другие методы того же класса и класса наследника. Впрочем, об этом подробно мы расскажем позднее.

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

На первый взгляд непонятно зачем нужен механизм защиты членов класса. Ответ простой: для того, чтобы не повредить класс. В самом деле, представьте себе, что в классе используется константа PI=3.1416 и переменная pi, значение которой может изменяться. Программист, создавая программы может ререпутать идентификаторы и вместо того, чтобы задать значение переменной изменит константу. Программа будет работать, но результат будет неверным. Именно для этого используются слова const и private.

 

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

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

Что дает инкапсуляция? Вспомним, что создавая обычную программу без использования классов, программист обязан держать в голове алгоритм, помнить имена переменных, констант и функций. При использовании классов программист не должен знать, как устроен класс и механизм его работы. Достаточно знать, какими методами обладает класс, и какие данные нужно использовать, чтобы обратиться к этим методам. Ярким примером обладания свойством инкапсуляции может являться легковой автомобиль. Большинство людей пользуются его возможностями (методами) не зная того как он работает.

Кстати говоря, попробуем ответить на вопрос: так ли уж нужно раскрывать все методы и данные класса для тех программистов, которые его будут использовать в своих программах? Ведь в автомобиле многие устройства управления его системами скрыты или вообще недоступны для водителя. Ответ, вероятно, ясен. Классы должны иметь возможность некоторые члены класса делать недоступными. Вот сейчас и посмотрим как это делается в С++.

Вы, конечно, обратили внимание на новое слово public,которое встретилось при описании класса. Это так называемый, спецификатор доступа. Всего существует 4 вида такого рода спецификаторов. Они носят названия private, protected, friend и уже встретившийся нам public. Спецификаторы доступа нужны для того, чтобы указать какие члены класса доступны пользователю, а какие нет. Кстати, по умолчанию все члены класса являются закрытыми.

Спецификатор public (общедоступный) означает максимальную степень доступности. Это означает, что члены класса, объявленные после ключевого слова public и до другого спецификатора доступны любому коду, как внутри класса, так и извне. После спецификатора обязательно ставится двоеточие. Обычно открытая часть, или, как говорят открытая секция располагается внутри класса первой.

Никаких требований к количеству данных или функций в секциях класса не предъявляется.

Спецификатор protected (защищенный) означает, что пользователям этого класса разрешается доступ к членам класса только через новые, производные от созданного, класса. Эта секция, как правило, является второй.

Спецификатор private (собственный) указывает, что попавшие в его сферу члены класса закрыты для посторонних. Обычно это данные и методы которые обеспечивают внутреннее функционирование класса, говоря иначе механику его работы. Доступ к закрытым членам можно осуществить только в теле определения функций-членов этого класса, Если попытаться получить доступ к переменной со спецификатором private в функции main или в определении некоторой функции, не являющейся функцией-членом этого класса, то компилятор выдаст сообщение об ошибке.

 

Синтаксис имеет вид:

 

 

Спецификатор friend (друг) предназначен для того, чтобы указать, что данной функцией или классом могут пользоваться другие функции или классы, отмеченные в специальном списке. Приведем пример. Предположим, что мы имеем некоторый класс, в котором необходимо знать является ли некоторый год високосным или нет. Это может быть, например, класс, описывающий историю спортивного движения. Известно, что олимпийские игры проводятся именно в високосном году. Пусть этот класс имеет имя Olimpic. Тогда для того, чтобы узнать могли ли быть олимпийские игры в определенном году можно воспользоваться классом clYear,который мы недавно рассматривали, но при этом сделаем в нем небольшие изменения.

class clYear {

friend int numberYear();

friend class Olimpic; //Класс друг

private: int days(int); /*Секция закрыта для всех,

кроме класса Olimpic */

};

 

Вот пример посложнее

#include <iostream.h>

#include <windows.h>

//using namespace std;

class DaysYear{

public:

void input();

void output();

void set(int newMonth, int newDay);

//int newMonth, int newDay – определяют дату

int getMonth(); //возвращает значение месяца (1-январь, 2-февраль..

int getDay(); //возвращает день месяца

private:

int month;

int day;

};

 

//===========================================================

void DaysYear::input(){

cout<<"Введите месяц ";

cin>>month;

cout<<"Введите день месяца ";

cin>>day;

}

void DaysYear::output(){

cout<<" месяц "<<month<<" день "<<day<<endl;

}

 

void DaysYear::set(int newMonth,int newDay){

month=newMonth;

day=newDay;

}

 

int DaysYear::getMonth(){

return month;

}

int DaysYear::getDay(){

return day;

}

 

 

//=========================================================

 

 

int main(){

DaysYear today, birthday;

SetConsoleOutputCP(1251);

cout<<"Введите текущую дату"<<endl<<endl;

today.input();

cout<<"Сегодня ";

today.output();

birthday.set(4,01);

cout<<"День дураков";

birthday.output();

if(today.getMonth()==birthday.getMonth() && today.getDay()==birthday.getDay())

cout<<"Чудаки украшают мир, а дураки губят его!"<<endl;

else cout<<"Желаем удачного дня"<<endl;

return 0;

}

 

 

Демонстрационные программы

Рассмотрим интересный класс с названием стек. С его помощью можно создать реальный стек. Напомним, что стек это устройство, работающее по принципу последним вошел – первым вышел. Примером такого устройства может являться детская игрушка – пирамида, представляющая собой стержень (stack) на который надеваются кольца разного диаметра. В этой игре первым со стека снимается кольцо, которое было надето последним. В нашей задаче, конечно, будет использоваться стек для чисел.

 

 

#include <iostream>

using namespace std;

#include <windows.h>

#define SIZE 100 //размер стека

//Определение класса stack

class stack{

int stck[SIZE]; /*массив,в котором хранятся числа,

записанные в стек, это не сам стек */

int tos; //переменная показывающая заполнение стека

public:

void init(); //функция инициализации стека

void push(int i); //функция записи (протягивания) в стек

int pop(); //функция уменьшения указателя очереди

};

//------конец класса, далее идет описание функций -------------

void stack::init(){ //установка указателя номера на ноль

tos=0;

}

//----------------------------

void stack::push(int i){

if(tos==SIZE){

cout<<”Стек полон”<<endl;

return;} // return говорит об окончании выполнения кода функции

stck[tos]=i;

tos++;

}

//-----------------------------

int stack::pop(){

if(tos==0){

cout<<”Стек пуст”<<endl;

return 0;

}

tos--;

return stck[tos];

}

//-------------------------

int main(){

stack stack1, stack2; //Создаем объекты класса stack

stack1.init(); //Опустошаем стеки

stack2.init();

stack1.push(1);

stack2.push(2);

stack1.push(3);

stack2.push(4);

cout<<stack1.pop()<<” “;

cout<<stack1.pop()<<” “;

cout<<stack2.pop()<<” “;

cout<<stack2.pop()<<” “;

return 0;

}

Результат работы программы

3 1 4 2

т.е. числа из обоих стеков выходят в обратном порядке.

Попробуйте на базе данного примера создать программу в которой имеется два стека. Числа в стеки записываются с клавиатуры. Количество записаных чисел в каждый стек может быть разным.

 

 

7.2. Конструкторы и деструкторы

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

class MyClass{

public:

int a,b,c;

void print();

};

void MyClass::print(){

cout<<”a=”<<a<<endl<<”b=”<<b<<endl<<”c=”<<c;

}

Нужно инициализировать переменные a,b,c.

Напомним, что класс состоит из объявлений и прототипов функций. Задать начальные значения перем



Поделиться:




Поиск по сайту

©2015-2024 poisk-ru.ru
Все права принадлежать их авторам. Данный сайт не претендует на авторства, а предоставляет бесплатное использование.
Дата создания страницы: 2016-02-16 Нарушение авторских прав и Нарушение персональных данных


Поиск по сайту: