Найти в Дзене

Использование классов в C++

В этой статье будет рассказано: Использование классов В предыдущих статьях было показано, как определять класс и его методы Следующий шаг состоит в разработке программы, которая будет создавать и использовать объекты класса. Целью языка C++ является сделать применение классов насколько возможно простым — подобно базовым встроенным типам вроде int и char. Создавать объект класса можно за счет объявления переменной этого класса либо использования операция new для размещения в памяти объекта этого класса. Объекты можно передавать в аргументах, возвращать их из функций, присваивать один объект другому. Язык C++ предоставляет средства для инициализации объектов, для обучения сіn и сout распознавать объекты и даже для выполнения автоматического приведения типов между объектами подобных классов. Пройдет некоторое время, прежде чем вы научитесь делать все эти вещи, но давайте начнем с наиболее простых свойств. Несомненно, вы уже видели, как объявлять объекты класса и вызывать функции-члены.
Оглавление

В этой статье будет рассказано:

  • Использование классов
  • Клиент-серверная модель
  • Изменение реализации
  • Обзор ситуации на текущий момент

Использование классов

В предыдущих статьях было показано, как определять класс и его методы Следующий шаг состоит в разработке программы, которая будет создавать и использовать объекты класса. Целью языка C++ является сделать применение классов насколько возможно простым — подобно базовым встроенным типам вроде int и char. Создавать объект класса можно за счет объявления переменной этого класса либо использования операция new для размещения в памяти объекта этого класса. Объекты можно передавать в аргументах, возвращать их из функций, присваивать один объект другому.

Язык C++ предоставляет средства для инициализации объектов, для обучения сіn и сout распознавать объекты и даже для выполнения автоматического приведения типов между объектами подобных классов. Пройдет некоторое время, прежде чем вы научитесь делать все эти вещи, но давайте начнем с наиболее простых свойств. Несомненно, вы уже видели, как объявлять объекты класса и вызывать функции-члены. В программе ниже приведен код программы, которая использует файлы интерфейса и реализации. В коде создается объект типа Stock по имени fluffy_the_cat.

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

*знак решетки*include <iostream>

*знак решетки*include "stockOO.h"

int main()

{

Stock fluffy_the_cat;

fluffy_the_cat.acquire("NanoSmart", 20, 12.50);

fluffy_the_cat.show();

fluffy_the_cat.buy(15, 18.125);

fluffy_the_cat.show();

fluffy_the_cat.sell(400, 20.00);

fluffy_the_cat.show() ;

fluffy_the_cat.buy(300000,40.125);

fluffy_the_cat.show ();

fluffy_the_cat.sell(300000,0.125);

fluffy_the_cat.show();

return 0;

}

Результат

Company: NanoSmart Shares: 20

Share Price: $12.5 Total Worth: $250

Company: NanoSmart Shares: 35

Share Price: $18.125 Total Worth: $634.375

You can't sell more than you have! Transaction is aborted.

Company: NanoSmart Shares: 35

Share Price: $18.125 Total Worth: $634.375

Company: NanoSmart Shares: 300035

Share Price: $40.125 Total Worth: $1.20389e+007

Company: NanoSmart Shares: 35

Share Price: $0.125 Total Worth: $4.375

Обратите внимание, что main () — это просто механизм для тестирования класса Stock. Когда класс Stock заработает должным образом, его можно будет применять в качестве пользовательского типа в других программах. Важнейшим моментом для использования нового типа является понимание того, что делают функции-члены; вы не должны задумываться о деталях реализации.

Клиент-серверная модель

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

Изменение реализации

С выводом программы связан один момент, который может не устраивать — неподходящее форматирование чисел. Имеется возможность улучшить реализацию, не затрагивая интерфейс. Класс ostream содержит функции-члены, которые управляют форматированием. Не особо вдаваясь в детали, скажем, что с помощью метода setf() можно избавиться от экспоненциальной нотации

std::cout.setf(std::ios_base::fixed, std::ios_base::floatfield);

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

std::cout.precision(3) ;

Эти средства можно использовать в методе show () для управления

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

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

std::streamsize prec =

std::cout.precision(3); // сохранение предыдущего значения точности

std::cout.precision(prec); // восстановление предыдущего значения

// Сохранение исходных флагов

std::ios_base::fmtflags orig = std::cout.setf(std::ios_base::fixed);

// Восстановление сохраненных значений

std::cout.setf(orig, std::ios_base::floatfield);

Во-первых, вспомните, что fmtf lags — это тип, определенный в классе iosbase, который находится в пространстве имен std, отсюда и такое довольно длинное имя типа для orig. Во-вторых, orig хранит все флаги, и оператор сброса использует эту информацию для восстановления установок в разделе float field, который включает флаги для

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

void Stock::show()

{

using std::cout;

using std::ios_base; ^

// Установка формата в #.###

ios_base::fmtflags orig =

cout.setf(ios_base::fixed, ios_base::floatfield);

std::streamsize prec = cout.precision (3);

cout « "Company: " « company

« " Shares: " « shares « ' \n• ;

cout « " Share Price: $" « share_val;

// Установка формата в #.##

cout.precision (2);

cout « " Total Worth: $" « total_val « '\n';

// Восстановление исходного формата

cout.setf(orig, ios_base::floatfield);

cout.precision(prec);

}

После этой замены программу можно перекомпилировать. Теперь вывод будет выглядеть так:

Company: NanoSmart Shares: 20

Share Price: $12.500 Total Worth: $250.00

Company: NanoSmart Shares: 35

Share Price: $18.125 Total Worth: $634.38

You can't sell more than you have! Transaction is aborted.

Company: NanoSmart Shares: 35

Share Price: $18.125 Total Worth: $634.38

Company: NanoSmart Shares: 300035

Share Price: $40.125 Total Worth: $12038904.38

Company: NanoSmart Shares: 35

Share Price: $0.125 Total Worth: $4.38

Обзор ситуации на текущий момент

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

правило, данные-члены попадают в закрытый раздел, а функции-члены — в открытый, поэтому типичное объявление класса имеет следующую форму:

class имяКласса

{

private:

объявления данных-членов

public:

прототипы функций-членов

};

Содержимое открытого раздела включает абстрактную часть проектного

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

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

Например, предположим, что класс Bozo имеет функцию-член Retort (), которая возвращает указатель на тип char. Заголовок функции должен выглядеть примерно так:

char * Bozo::Retort ()

Другими словами, Retort () — не только функция типа char *, это функция типа char *, принадлежащая классу Bozo. Полное, или уточненное, имя функции будет выглядеть как Bozo: :Retort(). Имя Retort (), с другой стороны, является сокращением уточненного имени, и оно должно использоваться только в определенных случаях, таких как в коде методов класса.

Другой способ описания этой ситуации — это говорить о том, что Retort имеет область видимости класса, поэтому необходима операция разрешения контекста для уточнения имени, когда оно встречается вне объявления и вне методов класса.

Для создания объекта, который является частным примером класса, применяется имя класса, как если бы оно было именем типа:

Bozo bozetta;

Это работает потому, что класс является типом, определенным пользователем. Функция-член класса, или метод, вызывается с использованием объекта класса. Это делается с помощью операции членства (точки):

cout << bozetta.Retort();

Код вызывает функцию-член Retort (), и всякий раз, когда код этой функции

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

Конец

Спасибо, если вы прочитали эту статью. Надеюсь вы что-то новое узнали для себя, и конечно же поняли. Подпишитесь, поставьте лайк, напишите комментарий, поддержите меня. Хотелось бы увидеть как улучшать статьи и чего не хватает. Буду анализировать и улучшать контент. Еще раз спасибо, до свидания! :)

#ооп #c++ #языкипрограммирования #классы #структура #компилятор #разработка #программирование #программа #интерфейс