Скачиваний:
316
Добавлен:
28.03.2021
Размер:
378.53 Кб
Скачать

32. Сравнение классов и структур. Сравнение классов и объединений

Структуры синтаксически очень похожи на классы, но существует принципиальное отличие, которое заключается в том, что класс – является ссылочным типом (reference type), а структуры – значимым типом (value type). Следовательно, классы всегда создаются в так называемой “куче” (heap), а структуры создаются в стеке (stack).Но это справедливо в очень простых случаях, главное отличие структур и классов: структуры передаются по значению (то есть копируются), объекты классов — по ссылке. Именно это является главным различием в их поведении, а не то, где они хранятся. Чем больше вы будете использовать структуры вместо маленьких классов, тем менее затратным по ресурсам будет использование памяти.Так же, как и классы, структуры могут иметь поля, методы и конструкторы.

Вопрос

Структура

Класс

Какого же типа экземпляр объекта?

Значимый (value) тип

Ссылочный (reference) тип

Где “живут” экземпляры этих объектов?

Экземпляры структуры называют значениями и “живут” они в стеке (stack).

Экземпляры классов называют объектами и “живут” они в куче (heap).

Можно ли создать конструктор по умолчанию?

Нет

Да

Если создается свой конструктор, будет ли компилятор генерировать конструктор по умолчанию?

Да

Нет

Если в своём конструкторе не будут инициализированы некоторые поля, будут ли они автоматически инициализированы компилятором?

Нет

Да

Разрешается ли инициализировать переменные там, где их объявляют?

Нет

ДА

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

Имеется несколько ограничений, которые необходимо иметь в виду при использовании объе­динений в С++. Первое — объединение не может наследовать какие-либо другие классы. Далее, объединение не может использоваться в качестве базового класса. Объединение не может иметь виртуальные функции-члены. Никакие статические переменные не могут быть членами объединения. Объединение не может иметь в качестве члена какой-либо объект, перегружающий оператор =. Наконец, никакой объект не может быть членом объединения, если этот объект имеет конструктор или деструктор.

18. Организация внешнего доступа к локальным компонентам класса. Встраиваемые методы класса. Использование встраиваемых методов в определении класса.

В С++ одна функция не может быть компонентом двух различных классов. В то же время иногда возникает необходимость организации доступа к локальным данным нескольких классов из одной функции. Для реализации этого в С++ введен спецификатор friend. Если некоторая функция определена как friend функция для некоторого класса, то она:

- не является компонентом-функцией этого класса;

- имеет доступ ко всем компонентам этого класса (private, public и protected).

Функции со спецификатором friend, не являясь компонентами класса, не имеют и, следовательно, не могут использовать this указатель.

В общем случае friend-функция является глобальной независимо от секции, в которой она объявлена (public, protected, private), при условии, что она не объявлена ни в одном другом классе без спецификатора friend. Функция friend, объявленная в классе, может рассматриваться как часть интерфейса класса с внешней средой.

Вызов компоненты-функции класса осуществляется с использованием операции доступа к компоненте «.» или «->». Вызов же friend-функции производится по ее имени.

В friend-функцию не передается this-указатель и доступ к компонентам класса выполняется либо явно «.», либо косвенно «->».

Компонент-функция одного класса может быть объявлена со спецификатором friend для другого класса.

Отметим основные свойства и правила использования спецификатора friend:

− friend-функции не являются компонентами класса, но имеют доступ ко всем его компонентам независимо от их атрибута доступа;

− friend-функции не имеют указателя this;

− friend-функции не наследуются в производных классах;

− отношение friend не является ни симметричным (т. е. если класс А friend классу В, то это не означает, что В также является friend классу А), ни транзитивным (т. е. если A friend B и B friend C, то не следует, что A friend C);

− друзьями класса можно определить перегруженные функции. Каждая перегруженная функция, используемая как friend для некоторого класса, должна быть явно объявлена в классе со спецификатором friend.

Встраиваемая функция – метод, код которого подставляется в то место программы, из которого он вызывается, т.е. вызов такого метода заменяется его кодом.

Два способа создания встраиваемых методов:

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

  2. Второй способ состоит в определении кода для метода класса в самом объявлении класса. Inline писать не обязательно. Для небольших методов это обычный стиль написания программ на С++.

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

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

class Cat {

public:

int GetWeight()

{

return itsWeight;

} // встраиваемая

void SetWeight(int aWeight);

} ;

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

class Cat {

public:

int GetWeight() const {

return itsWeight; } // встраиваемая

void SetWeight(int aWeight);

} ;