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




FOR

Чаще всего применяется цикл for. Синтаксис:

  for (инициализация; условие; обновление) { Исполняемый код }

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

  #include <iostream>   using namespace std; // Для cout и endl   int main() { // Цикл повторяется пока x < 10 и x увеличивается на 1 каждое повторение for (int x = 0; x < 10; x++) { //вывод x и переход на новую строку cout<< x <<endl; } cin.get(); }

WHILE

  while (x < 10) { // условие, пока x < 10 повторяем cout<< x <<endl; x++; // обновляем переменную }

Цикл while выполняется, пока условие в скобках — истина. while работает также как и for.

DO … WHILE

Циклы do…while полезны, когда должно произойти хотя бы одно повторение. Синтаксис:

  #include <iostream>   using namespace std;   int main() { int x;   x = 0; do { // "Hello, world!" будет напечатано хотя бы 1 раз // даже если x=0 cout<<"Hello, world!\n"; } while (x!= 0); cin.get(); }

Обратите внимание, что после цикла do…while необходима «;».

Операторif служит для того, чтобы выполнить какую-либо операцию в том случае, когда условие является верным. Условная конструкция в С++ всегда записывается в круглых скобках после оператора if.

Внутри фигурных скобок указывается тело условия. Если условие выполнится, то начнется выполнение всех команд, которые находятся между фигурными скобками.

Пример конструкции ветвления

if (num < 10) { // Если введенное число меньше 10.

cout << "Это число меньше 10." << endl;

} else { // иначе

cout << "Это число больше либо равно 10." << endl;

}

Здесь говорится: «Если переменная num меньше 10 — вывести соответствующее сообщение. Иначе, вывести другое сообщение».

Усовершенствуем программу так, чтобы она выводила сообщение, о том, что переменная numравна десяти:

if (num < 10) { // Если введенное число меньше 10.

cout << "Это число меньше 10." << endl;

} else if (num == 10) {

cout << "Это число равно 10." << endl;

} else { // иначе

cout << "Это число больше 10." << endl;

}

Каждому операторуif соответствует только один оператор else. Совокупность этих операторов — else if означает, что если не выполнилось предыдущее условие, то проверить данное. Если ни одно из условий не верно, то выполняется тело оператора else.

Если после оператора if, else или их связки else if должна выполняться только одна команда, то фигурные скобки можно не ставить. Предыдущую программу можно записать следующим образом:

#include <iostream>

using namespace std;

int main ()

{

setlocale(0, "");

double num;

cout << "Введите произвольное число: ";

cin >> num;

if (num < 10) // Если введенное число меньше 10.

cout << "Это число меньше 10." << endl;

else if (num == 10)

cout << "Это число равно 10." << endl;

else // иначе

cout << "Это число больше 10." << endl;

return 0;

}

5) Синтаксис определения структуры и структурной переменной. Доступ к полям структуры. Присвоение структурных переменных.

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

  struct Name { type atrib; // остальные элементы структуры } structVar1, structVar2,...;

где,

struct — ключевое слово, которое начинает определение структуры

Name — имя структуры

type — тип данных элемента структуры

atrib — элемент структуры

structVar1-2 — структурные переменные

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

car.speed;

Чтобы получить доступ к элементам структуры, через указатель на структуру, вместо оператора «точка», используйте оператор стрелка ->:

  carPtr->speed;

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

Раньше:

john.id = 5;

john.age = 27;

john.salary = 45000.0;

с С++ 11:

john = { 5, 27, 45000.0 };

6) Синтаксис определения и инициализации указателя на структуру. Работа с полями структуры через указатель.

Определение структуры в языке С++ начинается с ключевого слова struct. Затем следует имя структуры, в данном случае этим именем является part. Объявления полей струк­туры modelnumber, partnumber и cost заключены в фигурные скобки. После за­крывающей фигурной скобки следует точка с запятой (;) – символ, означающий конец определения структуры. Обратите внимание на то, что использование точки с запятой после блока операторов при определении структуры отличает синтаксис структуры от синтаксиса других рассмотренных нами элементов про­граммы. Как мы видели, в циклах, ветвлениях и функциях блоки операторов тоже ограничивались фигурными скобками, однако точка с запятой после таких блоков не ставилась.

 

 

struct part
{

 

int modelnumber;
int partnumber;

 

float cost;
};

 

инициализация указателя на структуру

Вот самое простое описание, какое только может быть:

struct guy *him;

Первым стоит ключевое слово struct, затем слово guy, являющееся именем структурного шаблона, далее * и за нею имя указателя. Синтаксис тот же, как для описаний других указателей, которые мы видели.

Теперь можно создать указатель him для ссылок на любые структуры типа guy. Мы инициализируем him, заставляя его ссылаться нa fellow[0]; заметим, что мы используем операцию получения адреса:

him = &fellow[0];

Первые две выведенные строки показывают результат этого присваивания. Сравнивая две строки, мы видим, что him ссылается на fellow[0], a him+1 - на fellow[l]. Заметим, что добавление 1 к him прибавляет 84 к адресу. Это происходит потому, что каждая guy-структура занимает 84 байта памяти: первое имя - 20, последнее имя - 20, favfood - 20, job - 20 и income - 4 байта (размер элемента типа float в нашей системе).

spisok* p = new spisok;

strcpy(p ->book, "book");

strcpy(p ->name, "seferus");

p - указатель на структуру, p ->book - обращение к полю структуры через указатель на структуру.

7) Синтаксис перечисления. Синтаксис объединения. Особенности размещения в памяти и доступности элементов перечисления и объединения.

Перечисления (enum) используются в C++ для создания констант. Допустим надо объявить константы для музыкальных нот и каждую инициализировать соответствующим порядковым номером. Можно воспользоваться уже знакомым нам способом:

Такое объявление занимает много строк кода и не совсем удобно. Используя перечисление, можно определить эти константы иным способом. Синтаксис enum похож на синтаксис структур: ключевое слово — дескриптор — элементы в фигурных скобках через запятую:

Это полная форма — с дескриптором (именем перечисления). Как и в случае со структурами, имя перечисления можно не использовать:

В первом случае — мы сможем создавать переменные типа перечисления notes. Во втором случае — нет.

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

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

union [name] { member-list };

member-list:

char ch; int i; long l; float f; double d; int *int_ptr;

 

 

8) Определение функции. Передача аргументов и возврат значений по значению, ссылке и через указатель. Аргументы по умолчанию. Константные аргументы функции.

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

int sum(int a, int b) { return a + b; }

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

int main() { int i = sum(10, 32); int j = sum(i, 66); cout << "The value of j is" << j << endl; // 108 }

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

При объявлении функции необходимо указать:

Возвращаемый тип, представляющий собой тип значения, возвращаемого функцией. Если возвращать значение не требуется, укажите void. Например, в C++11 можно использовать возвращаемый тип auto, отдающий компилятору команду определять тип в соответствии с оператором return. Тип decltype (auto) также используется в C++14. Дополнительные сведения см. в подразделе "Выведение возвращаемых типов" ниже.

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

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

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

Помимо нескольких исключений, С для передачи аргументов использует передачу по значению. Это означает, что обычно нельзя изменять переменные, используемые при вызове функции. Рассмотрим следующую функцию:
#include <stdio.h>
int sqr (int x);
int main(void)
{
int t=10;
printf("%d %d", sqr(t), t);
return 0;
}
int sqr (int x) {
x = x*x; return x;
}
В данном примере значение аргумента, передаваемого в sqr(), 10, копируется в параметр х. Когда происходит присваивание х = х * х, модифицируется только локальная переменная х. Переменная t, используемая при вызове sqr(), по-прежнему содержит значение 10. Следовательно, на экране появится «100 10».

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

double heron_space(const double a = 5, const double b = 6.5, const double c = 10.7); //параметры функции инициализированы по умолчанию

cout << "S = " << heron_space() << endl << endl; // все параметры используются по умолчанию

cout << "S = " << heron_space(10,5) << endl << endl; // только последний параметр используется по умолчанию

cout << "S = " << heron_space(7) << endl << endl; // два последних параметра берутся по умолчанию, а первый равен 7

 

Параметры функции инициализированы по умолчанию в прототипе функции. Если при запуске функции не передавать ей значения, то по умолчанию будут использоваться аргументы 5, 6.5, 10.7. В строках 12, 13, 14 показаны различные способы использования функции heron_space() с аргументами по умолчанию. Данная функция heron_space вычисляет площадь треугольников по формуле Герона.Формула Герона позволяет вычислить площадь треугольника (S) по его сторонам a, b, c:

return (sqrt(p * (p - a) * (p - b) * (p - c))); // формула Герона для нахождения площади треугольника

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

//объекты на которые ссылаются a и b

//внутри функции доступны только для чтения

void anyfunc(const int *a, const int &b);

9) Перегруженные функции. Встраиваемые функции. Рекурсивные функции.

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

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

В следующей программе определены три перегруженные функции с именем sumElements(). Все они вычисляют сумму элементов массивов. Одна принимает массив типа int и его размер. Вторая принимает массив типа double и его размер. Третья принимает два массива с типом элементов int и double и их размер.

int sumElements(int arrI[], int size);

double sumElements(double arrD[], int size);

double sumElements(int arrI[], double arrD[], int size);

 

В C++ можно задать функцию, которая на самом деле не вызывается, а ее тело встраивается в программу в месте ее вызова. Преимуществом встраиваемых (in-line) функций является то, что они не связаны с механизмом вызова функций и возврата ими своего значения. Это значит, что встраиваемые функции могут выполняться гораздо быстрее обычных.

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

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

Для объявления встраиваемой функции просто впишите спецификатор inline перед определением функции.

// Пример встраиваемой функции

#include <iostreara>

using namespace std;

 

inline int even (int x)

{

return! (x%2);

int main ()

{

if (even (10)) cout ≪ "10 является четным\п";

if (even (11)) cout ≪ "11 является четным\п";

return 0;

}

</iostreara>

 

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

Пример 1. Вычислить факториал числа. Использовать рекурсивную функцию.

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

#include <iostream>

using namespace std;

int fact(int n);

int main()

{

int a;

cout << "Enter number: " << endl;

cin >> a;

cout << fact(a) << endl;

return 0;

}

int fact(int n)

{

int f;

if (n == 0)

f = 1;

else

f = n * fact(n - 1);

return f;

}

 

10) Область видимости и класс памяти.

 

11) Объявление и инициализация одномерного и многомерного массива. Работа с элементами массива через указатель.

Массивы – это группа однородных данных, имеющих один и тот же тип и одно и тоже имя.

Объявление: (тип_имя_кол-во. Элементов) int month или double mas

Инициализация: int mas={1, 2, 3, 4, 5} или с клавиатуры. For(int i=0; i<12; ++i)

Общая форма объявления многомерного массива

тип имя[размерность1][размерность2]...[размерностьm];

Многомерные массивы задаются указанием каждого измерения в квадратных скобках, например, оператор

int matr [6][8];

задает описание двумерного массива из 6 строк и 8 столбцов. В памяти такой массив располагается в последовательных ячейках построчно. Многомерные массивы размещаются так, что при переходе к следующему элементу быстрее всего изменяется последний индекс. Для доступа к элементу многомерного массива указываются все его индексы, например, matr[i][j], или более экзотическим способом: *(matr[i]+j) или *(*(matr+i)+j). Это возможно, поскольку matr[i] является адресом начала i-й строки массива.

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

int mass2 [][2] = { {1, 1}, {0, 2}, {1, 0} }: int mass2 [3][2] = {1, 1, 0, 2, 1, 0}

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

Объявление указателя имеет следующий синтаксис:

<тип> * <идентификатор> [ = <инициализатор> ];

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

int *pi; // Указатель на int
char *ppc; // Указатель на указатель на char
int* p, s; // Плохой стиль объявления, s – не указатель!
int *p, s; // Видно, что s – не указатель
int *p, *s; // Два указателя
char *names[] = {"John", "Anna"}; // Массив указателей

В последнем объявлении для формирования типа используются два оператора: * и [ ], один из которых стоит перед именем, а другой – после. Использование операторов объявления значительно упростилось бы, будь они все либо префиксами, либо суффиксами. Однако, *, [] и () разрабатывались так, чтобы отражать их смысл в выражениях. Таким образом, * является префиксом, а [] и () – суффиксами. Суффиксные операторы «крепче связаны» с именем, чем префиксные. Следовательно, *names[] означает массив указателей на какие-либо объекты, а для определения типов наподобие «указатель на функцию», необходимо использовать скобки.

Существуют две операции, которые имеют отношение к работе с указателями. Этими операциями являются:

операция взятия адреса (адресация) &;

операция взятия значения по адресу (косвенная адресация или разыменование) *.

 

12) Передача массивов в функцию. Возвращение массива функцией.

Когда массив используется в качестве аргумента функции, передается только адрес массива, а не копия всего массива. При вызове функции с именем массива в функцию передается указатель на первый элемент массива. (Надо помнить, что в С имена массивов без индекса - это указатели на первый элемент массива.) Параметр должен иметь тип, совместимый с указателем. Имеется три способа объявления параметра, предназначенного для получения указателя на массив. Во-первых, он может быть объявлен как массив, как показано ниже:
#include <stdio.h>
void display(int num[10]);
int main (void) /* вывод чисел */
{
int t [10], i;
for (i=0; i<10; ++i) t[i]=i;
display(t);
return 0;
}
void display(int num[10])
{
int i;
for (i=0; i<10; i++) printf ("%d", num[i]);
}
Хотя параметр num объявляется как целочисленный массив из десяти элементов, С автоматически преобразует его к целочисленному указателю, поскольку не существует параметра, который мог бы на самом деле принять весь массив. Передается только указатель на массив, поэтому должен быть параметр, способный принять его.

Следующий способ состоит в объявлении параметра для указания на безразмерный массив, как показано ниже:
void display(int num[])
{
int i;
for (i=0; i<10; i++) printf("%d ", num[i]);
}
где num объявлен как целочисленный массив неизвестного размера. Поскольку С не предоставляет проверку границ массива, настоящий размер массива не имеет никакого отношения к параметру (но, естественно, не к программе). Данный метод объявления также определяет num как целочисленный указатель.

Последний способ, которым может быть объявлен num, - это наиболее типичный способ, применяемый при написании профессиональных программ, - через указатель, как показано ниже:
void display(int *num)
{
int i;
for (i=0; i<10; i++) printf ("%d ", num[i]);
}

C ++ не позволяет возвращать весь массив в качестве аргумента функции. Тем не менее, вы можете вернуть указатель на массив, указав имя массива без индекса.

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

int * myFunction()

{

.

.

.

}

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

int * getRandom()

{

static int r[10];

// set the seed

srand((unsigned)time(NULL));

for (int i = 0; i < 10; ++i)

{

r[i] = rand();

cout << r[i] << endl;

}

return r;

}

13) Принципы объектно-ориентированного программирования. Инкапсуляция. Наследование. Полиморфизм.

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

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

Полиморфизм — это явление, при котором функции (методу) с одним и тем же именем соответствует разный программный код (полиморфный код) в зависимости от того, в каком контексте он вызывается (объектами какого класса или с какими параметрами).

14) Классы и объекты в языке С++. Члены класса. Определение класса (поля, методы, доступ к членам класса). Определение методов в классе и вне класса.

Классы в С++ — это абстракция описывающая методы, свойства, ещё не существующих объектов. Объекты — конкретное представление абстракции, имеющее свои свойства и методы. Созданные объекты на основе одного класса называются экземплярами этого класса

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

// объявление классов в С++

class /*имя класса*/

{

private:

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

public:

/* список методов доступных другим функциям и объектам программы */

protected:

/*список средств, доступных при наследовании*/

};

Объявление класса начинается с зарезервированного ключевого слова class,послекоторого пишется имя класса. В фигурных скобочках, строки 3 — 10 объявляется тело класса, причём после закрывающейся скобочки обязательно нужно ставить точку с запятой, строка 10. В теле класса объявляются три метки спецификации доступа, строки 4, 6, 8, после каждой метки нужно обязательно ставить двоеточие. В строке 4 объявлена метка спецификатора доступа private. Все методы и свойства класса, объявленные после спецификатор доступа private будут доступны только внутри класса. В строке 6 объявлен спецификатор доступа public, все методы и свойства класса, объявленные после спецификатора доступа public будут доступны другим функциям и объектам в программе. Пока на этом остановимся, спецификатор доступа protected разбирать сейчас не будем, просто запомните, что он есть. При объявлении класса, не обязательно объявлять три спецификатора доступа, и не обязательно их объявлять в таком порядке. Но лучше сразу определиться с порядком объявления спецификаторов доступа, и стараться его придерживаться. Разработаем программу, в которой объявим простейший класс, в котором будет объявлена одна функция, печатающая сообщение.

// classes.cpp: определяет точку входа для консольного приложения.

 

#include "stdafx.h"

#include <iostream>

using namespace std;

// начало объявления класса

class CppStudio // имя класса

{

public: // спецификатор доступа

void message() // функция (метод класса) выводящая сообщение на экран

{

cout << "website: cppstudio.com\ntheme: Classes and Objects in C + +\n";

}

}; // конец объявления класса CppStudio

 

int main(int argc, char* argv[])

{

CppStudio objMessage; // объявление объекта

objMessage.message(); // вызов функции класса message

system("pause");

return 0;

}

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

Ниже приведен полный список категорий членов:

Специальные функции-члены. Функции-члены. Элементы данных, включая встроенные типы и другие пользовательские типы. Операторы. Объявления вложенных классов. Объединения. Перечисления. Битовые поля. Дружественные объекты. Псевдонимы и определения типов.

 

15) Конструкторы и деструкторы. Конструктор копирования по умолчанию.

Конструктор (от construct – создавать) — это особый метод класса, который выполняется автоматически в момент создания объекта класса. То есть, если мы пропишем в нем, какими значениями надо инициализировать поля во время объявления объекта класса, он сработает без «особого приглашения». Его не надо специально вызывать, как обычный метод класса.

class SomeData

{

private:

int someNum1;

double someNum2;

char someSymb[128];

public:

SomeData() //это конструктор:

{

someNum1 = 111; // присваиваем начальные значения полям

someNum2 = 222.22;

strcpy_s(someSymb, "СТРОКА!");

cout << "\nКонструктор сработал!\n";

}

 

void showSomeData()

{

cout << "someNum1 = " << someNum1 << endl;

cout << "someNum2 = " << someNum2 << endl;

cout << "someSymb = " << someSymb << endl;

}

}obj1; //уже на этом этапе сработает конструктор (значения запишутся в поля)

 

Деструктор (от destruct — разрушать) — так же особый метод класса, который срабатывает во время уничтожения объектов класса. Чаще всего его роль заключается в том, чтобы освободить динамическую память, которую выделял конструктор для объекта. Имя его, как и у конструктора, должно соответствовать имени класса. Только перед именем надо добавить символ ~

class SomeData

{

private:

int someNum1;

double someNum2;

char someSymb[128];

public:

SomeData()

{

someNum1 = 0;

someNum2 = 0;

strcpy_s(someSymb, "СТРОКА ПО УМОЛЧАНИЮ!");

cout << "\nКонструктор сработал!\n";

}

 

SomeData(int n1, double n2, char s[])

{

someNum1 = n1;

someNum2 = n2;

strcpy_s(someSymb, s);

cout << "\nКонструктор с параметрами сработал!\n";

}

 

void showSomeData()

{

cout << "someNum1 = " << someNum1 << endl;

cout << "someNum2 = " << someNum2 << endl;

cout << "someSymb = " << someSymb << endl;

}

 

~SomeData()

{

cout << "\nДеcтруктор сработал!\n";

}

};

Конструктор копирования необходим для того, чтобы мы могли создавать «реальные» (а не побитовые) копии для объектов класса. Такая копия объекта может понадобиться в следующих случаях:

при передаче объекта класса в функцию, как параметра по значению (а не по ссылке);

при возвращении из функции объекта класса, как результата её работы;

при инициализации одного объекта класса другим объектом этого класса.

  НазваниеКласса (const НазваниеКласса& object) { // код конструктора копирования }

class OneClass

{

int *ptr; // какой-то указатель

 

public:

OneClass() // конструктор без параметров

{

cout << "\nСработал Конструктор без параметров\n";

}

 

OneClass(const OneClass &object)

{

cout << "\nСработал Конструктор копирования\n";

}

 

~OneClass()

{

cout << "\nСработал Дестркуктор\n";

}

};

 

void showFunc(OneClass object)

{

cout << "\nЭта функция принимает объект класса, как параметр.\n";

cout << "Сначала срабатывает конструктор копирования (т.к. создается реальная копия объекта).\n";

cout << "Затем выполняется код функции. А при выходе из нее - сработает деструктор.\n";

}

 

OneClass returnObjectFunc()

{

OneClass object; // тут сработает конструктор без параметров

cout << "\nЭта функция возвращает объект.\n";

cout << "При выходе из нее, деструктор сработает дважды.\n";

return object; // тут сработает конструктор копирования

}

16) Объекты как аргументы методов и доступ к их членам.

 

17) Размещение в памяти членов объектов одного класса и способ создания общих полей (свойств).

 

18) Константные методы, их аргументы и константные объекты.

 

 

19) Строки на основе char массива и класса string.

 

20) Перегрузка унарных операций.

 

 

21) Перегрузка бинарных операций.

 

22) Перегрузка операций индексации массива [].

 

 

23) Преобразование типов от основного к пользовательскому.

 

24) Преобразование типов от пользовательского к основному.

 

 

25) Преобразование типов от пользовательского к пользовательскому.

 

26) Предотвращение преобразование типа от основного к пользовательскому с помощью конструктора.

 

 

27) Базовый и производный классы. Конструкторы производного класса. Перегрузка методов при наследовании. Алгоритм выбора перегруженного метода.

 

28) Общее и частное наследование. Уровни наследования. Множественное наследование. Неопределенность при множественном наследовании. Алгоритм выбора перегруженного метода.

 

 

29) Указатели. Инициализация, арифметические операции.

 

30) Управление памятью: операции new и delete. Указатель this.

 

 

31) Виртуальные функции.

 

32) Дружественные функции.

 

 

33) Статические функции.

 

 



Поделиться:




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

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


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