Типы данных. Преобразования типов.




Основные типы данных:

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

Преобразования типов. В языке С++ предусмотрено автоматическое и явное преобразование типов. Автоматическое приведение типов имеет следующую иерархию. Если тип одного операнда long double, другой преобразуется в long double. Если тип одного операнда double, другой операнд преобразуется в double; или float, другой преобразуется в float; Иначе преобразуются оба операнда: char, signed, char, unsigned char, short int и unsigned short int преобразуются в int, если int может представить все значения исходных типов, иначе они преобразуются в unsigned int; bool преобразуется в int. Если тип одного операнда unsigned long, другой операнд преобразуется к типу unsigned long: если тип одного операнда long int,а другого unsigned int, то если long int может представить все значения типа unsigned int, unsigned int преобразуется в long int, иначе оба операнда преобразуются в unsigned long int; иначе, если тип одного операнда long int, другой операнд преобразуется в long int, иначе, если тип одного операнда unsigned int другой операнд преобразуется в unsigned int; иначе оба операнда имеют тип іnt.

Пример использования автоматического преобразования типов:

#include <iostream>

using namespace std;

int main()

{ int sajen = 7;

float koeff = 2.1336F;

double rasst = sajen * koeff; // автоматическое приведение к типу double cout << "Расстояние " << sajen << " равно " << rasst << " м" << endl; return 0 }

Для явного преобразования типов используются операции:

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

Преобразование const_cast аннулирует действие модификатора const.

Операции приведения типов имеют следующий синтаксис:

Пример использования явного преобразования типов:

#include <iostream>

using namespace std;

int main()

{ int intVar = 1500000000;

intVar = (static_cast(intVar)*10)/10; //явное приведение к double

cout << "Значение intVar равно " << intVar << endl;

return 0; }

 

Для ввода/вывода в С++ использ­­­­­­уют потоки ввода и вывода. Для этого необходимо включить заголовочный файл <iostream>. Для ввода используется операция >>, для вывода — операция <<. Компилятор определяет тип вводимой/выводимой переменной и соответствующим образом форматирует её. Если при вводе или выводе произошла ошибка, в переменной состояния потока устанавливается соответствующий флаг. Проверить его значение можно с помощью функции fail. Использования потоков ввода-вывода:

#include <iostream>

using namespace std;

int main()

{ int ftemp;

cout << "Введите температуру по Фаренгейту: ";

cin >> ftemp;

if (cin.fail()) //Обнаружение ошибок

cout << "Произошла ошибка при вводе" << endl;

int ctemp = (ftemp‐32)*5 / 9;

cout << "Температура no Цельсию равна " << ctemp << endl;

return 0;}

Манипуляторы ввода-вывода управляют форматом вводимого/выводимого значения. Это функций, которые вставляются между вводимыми/выводимыми значениями и изменяют состояние потока. Для использования манипуляторов необходимо включить заголовочный файл <iomanip>.

Стандартные манипуляторы ввода-вывода:

использования манипулятора setw:

#include <iostream>

#include <iomanip> // для использования setw

using namespace std;

int main()

{ long nas1 = 8425785, nas2 = 4761, nas3 = 9761;

cout << setw(9) << "Город" << setw(12) << "На‐ селение" << endl << setw(9) << "Москва" << setw(12) << nas1 << endl << setw(9) << "Киров" << setw(12) << nas2 << endl << setw(9) << "Угрюмовка" << setw(12) << nas3 << endl;

return 0; }

 

 

3. Операции отношения. Логические операции. Приоритеты операций С++.

Операции отношения используются для сравнения значений в условных выражениях. Значения могут быть как стандартных типов языка C++, так и типов, определяемых пользователем (в таком случае оператор должен быть переопределен). Сравнение устанавливает одно из трех возможных отношений между переменными: равенство, больше, меньше. Результатом сравнения является значение истина(1) или ложь(0). Несмотря на то, что в большинстве случаев, для представления истинного значения используют 1, любое отличное от нуля число будет воспринято как истинное, операция эквивалентности, в отличие от операции присваивания, обозначается с помощью двойного знака равенства. Примеры условных выражений: a>0; num<=100; ‘c’== ‘C’; ‘c’!=‘C’.
Логические операции — операции, позволяющие производить действия над булевыми переменными, то есть переменными, обладающими только двумя значениями — истина и ложь.

Приоритет_операций.

4.Циклы и ветвления. Иногда необходимо повторять одно и то же действие несколько раз подряд. Для этого используют циклы.Если мы знаем точное количество действий (итераций) цикла, то можем использовать цикл for.Итерацией цикла называется один проход этого циклаСчетчик цикла — это переменная, в которой хранится количество проходов данного цикла.Описание синтаксиса1. Сначала присваивается первоначальное значение счетчику, после чего ставится точка с запятой.2. Затем задается конечное значение счетчика цикла. После того, как значение счетчика достигнет указанного предела, цикл завершится. Снова ставим точку с запятой.3. Задаем шаг цикла. Шаг цикла — это значение, на которое будет увеличиваться или уменьшаться счетчик цикла при каждом проходе.Пример кода:#include <iostream>using namespace std;int main(){int i; // счетчик циклаint sum = 0; // сумма чисел от 1 до 1000.setlocale(0, "");for (i = 1; i <= 1000; i++) // задаем начальное значение 1, конечное 1000 и задаем шаг цикла - 1. {sum = sum + i;}cout << "Сумма чисел от 1 до 1000 = " << sum << endl;return 0;} Цикл while Когда мы не знаем, сколько итераций должен произвести цикл, нам понадобится цикл while или do...while.#include <iostream>using namespace std;int main(){setlocale(0, "");int i = 0; // инициализируем счетчик цикла.int sum = 0; // инициализируем счетчик суммы.while (i < 1000){i++;sum += i;}cout << "Сумма чисел от 1 до 1000 = " << sum << endl;return 0;} Цикл do while Цикл do while очень похож на цикл while. Единственное их различие в том, что при выполнении цикла do while один проход цикла будет выполнен независимо от условия.#include <iostream>using namespace std;int main (){setlocale(0, "");int i = 0; // инициализируем счетчик цикла.int sum = 0; // инициализируем счетчик суммы.do {// выполняем цикл.i++;sum += i;} while (i < 1000); // пока выполняется условие.cout << "Сумма чисел от 1 до 1000 = " << sum << endl;return 0;}Ветвления. Оператор if Оператор if служит для того, чтобы выполнить какую-либо операцию в том случае, когда условие является верным.Каждому оператору if соответствует только один оператор else. Совокупность этих операторов — else if означает, что если не выполнилось предыдущее условие, то проверить данное. Если ни одно из условий не верно, то выполняется тело оператора else.#include <iostream>using namespace std;int main(){setlocale(0, "");double num;int k; cout << "Введите произвольное число: "; cin >> num;if (num < 10) { // Если введенное число меньше 10.cout << "Это число меньше 10." << endl;k = 1;} else if (num == 10) {cout << "Это число равно 10." << endl;k = 2;} else { // иначеcout << "Это число больше 10." << endl;k = 3;}cout << "k = " << k << endl;return 0;}

 

 

5. Синтаксис определения структуры и структурной переменной. Доступ к полям структуры. Присвоение структурных переменных. Определение структуры начинается с ключевого слова struct, затем следует имя структуры. Объявления полей структуры заключены в фигурные скобки. После закрывающей фигурной скобки следует точка с запятой (;). Далее рассмотрим определение переменной. Переменная типа, определенного пользователем, объявляется двумя способами: 1) при определении структуры struct part { int modelnumber; int partnumber; float cost; } 2) после определения структуры part p1, p2; Определение переменной означает, что под эту переменную выделяется память. Под структурную переменную всегда отводится столько памяти, сколько достаточно для хранения всех ее полей. Доступ к полям структуры. Когда структурная переменная определена, доступ к ее полям возможен с применением операции точки. В следующей строчке первому из полей структуры part присваивается значение при помощи оператора «=»: p1.modelnumber = 6244; Поле структуры идентифицируется с помощью трех составляющих: имени структурной переменной p1, операции точки (.) и имени поля modelnumber. Присваивание структурных переменных: p2=p1; Значение каждого поля переменной p1 присваивается соответствующему полю переменной p2. Нельзя присваивать переменные разных структур друг другу, даже если шаблоны структур совпадают.

6. Синтаксиз опредедления и инициализации указателя на структуру. Работа с полями структуры через указатель. Указатели - это переменные, в которых хранится адрес других переменных. Используются два основных оператора: * — показывает, кто живет в этом номере (показывает значение переменной по заданному адресу). Если вы используете оператор *, то вы занимаетесь операцией разыменование указателя. Так по другому называется использование оператора *. & — говорит, по какому адресу проживает этот человек (показывает адрес переменной). При объявлении указателя на структуру, как и в случае создания указателей на значения базовых типов, указывается тип структуры, а перед именем переменной указателя ставится оператор *. Этот же оператор используется для получения доступа к переменной структуры по указателю на эту переменную. Кроме того, через указатель на структуру можно обращаться непосредственно к полям структуры, для чего используют оператор -> (стрелка, состоит из двух символов - и >). Например, если в программе определен указатель на переменную структуры, у которой есть поле, то доступ к этому полю можно получить с помощью инструкции указатель->поле. Пример: #include <iostream> using namespace std; struct Numbers {int integer; double real; char symbol;}; void show(Numbers x) //вертуальная функция в этой прогрумме нужна, для вывода {cout << "Integer: "<<x. integer << endl; cout << "Real: "<<x. real << endl; cout << "Symbol: " << x. symbol << endl<<endl;} int main() {Numbers a,b; Numbers *p,*q; p=&a; q=&b; p->integer=1; p->real=2.5; p->symbol= 'a'; (*q).integer=2; (*q).real=5.1; (*q).symbol='b'; show(a); show(*q); return 0;} Работа с полями структуры через указатель. Пример: #include <iostream> using namespace std; truct Spisok {char name[100]; char book[30];}; int main () {Spisok bible; cin>>bible.book; cin>>bible.name; Spisok* bpointer; //"bpointer" - указатель на структуру bpointer = &bible; cout << bpointer->book << " "<< bpointer->name; /*"bpointer ->book" - обращение к полю структуры через указатель на структуру.*/ return 0;}

 

7.Синтаксис перечисления. Синтаксис объединения. Особенности размещения в памяти и доступности элементов перечисления и объединения. Перечисляемый тип задаёт тип, который является подмножеством целого типа. Синтаксис:enum [<тег>] {<список перечисления>} <описатель>[, <описатель>...];enum <тег> <описатель> [,<описатель>...];Тег предназначен для различения нескольких перечислимых типов, объявленных в одной программе.Список перечисления содержит одну или более конструкций вида:<идентификатор>[=<константное выражение> ]Конструкции в списке разделяются запятыми. Каждый идентификатор именует элемент списка перечисления. По умолчанию, если не задано константное выражение, первому элементу присваивается значение 0, следующему элементу — значение 1 и т. д.Пример// объявление перечисляемого типаenum days_of_week { Sun, Mon, Tue, Wed, Thu, Fri, Sat };int main(){days_of_week day1, day2; // определения переменных, хранящих дни неделиday1 = Mon; // инициализация переменныхday2 = Thu; int diff = day2 — day1; // арифметическая операцияcout << "Разница в днях: " << diff << endl; if(day1 < day2) // сравнениеcout << "day1 наступит раньше, чем day2\n";return 0;} Объединения - это объект, позволяющий нескольким переменным различных типов занимать один участок памяти. Объявление объединения похоже на объявление структуры: union union_type { int i; char ch; };Как и для структур, можно объявить переменную, поместив ее имя в конце определения или используя отдельный оператор объявления. Для объявления переменной cnvt объединения union_type следует написать: union union_type cnvt;Объединение применяется для следующих целей:- инициализации используемого объекта памяти, если в каждый момент времени только один объект из многих является активным;- интерпретации основного представления объекта одного типа, как если бы этому объекту был присвоен другой тип.Особенности размещения в памяти и доступности элементов перечисления и объединения?

8.Определение функции. Передача аргументов и возврат значений по значению, ссылке и через указатель. Аргументы по умолчанию. Константные аргументы функции. В C++, функции не должны быть определены до момента их использования, но они должны быть ранее объявлены. Но даже после всего этого, эта функция должна быть определена. После этого прототип функции и ее определение связываются, и эта функция может быть использована.Если функция ранее была объявлена, она должна быть определена с тем же возвращаемым значением и типами данных, в противном случае, будет создана новая, перегруженная функция. Имена параметров функции не должны быть одинаковыми.void aFunc(int& a, const int& b); // прототип функции int main() { int alpha = 7; int beta = 11; aFunc(alpha, beta); return 0; } void aFunc(int& a, const int& b) // определение функции { a = 107; // корректно b = 111; /* ошибка при попытке изменить кон‐ стантный аргумент*/ }В языке С++ существует 3 способа передачи аргументов в функцию: • передача аргумента по значению; • передача с использованием указателя на аргумент; • передача аргумента по ссылке. Передача по значению. Данный метод копирует содержимое аргумента в формальный параметр подпрограммы. Изменения, сделанные в параметре, не влияют на значение переменной, используемой при вызове. Передача по ссылке. В данном методе копируется адрес аргумента. В подпрограмме адрес используется для доступа к настоящему аргументу, используемому при вызове. То есть, изменения, сделанные в параметре, влияют на содержимое переменной, используемой при вызове. Передача через указатель. В случае, если функция должна менять свои аргументы, можно использовать указатели. Указатели также передаются по значе- нию, внутри функции создается локальная переменная-указатель. Но, так как этот указатель инициализируется адресом переменной из вызываемой программы, то эту переменную можно менять, ис- пользуя этот адрес. Если передавать параметры через указатель код функции выглядит так:mul5(int *x){*x = *x * 5;}Вызов:int var=10;mul5(&var); // Здесь символ & обозначает операцию взятия адреса переменной аргументы по умолчанию. Аргументы по умолчанию. В языке С++ можно задавать так называемые параметры функции по умолчанию. Если в объявлении формального параметра задано выражение, то оно воспринимается как умолчание этого параметра. Все последующие пара- метры также должны иметь умолчания. Умолчания параметров подставляются в вызов функции при отсутствии в нём последних по списку параметров. Примером аргументов по умолчанию являются переменные x и у функции sum_cvad #include using namespace std; inline float sum_cvad(float x = 0.0F, float y = 0.0F) { return (x * x + y * y); } int main() { float a, b; cout << "Введите два числа "; cin >> a >> b; cout << "a^2 + b^2 = " << sum_cvad(a,b) << endl; cout << "a^2 = " << sum_cvad(a) << endl; /*верно, т.к. по умолчанию второй аргумент равен нулю.*/ return 0; } Константные аргументы функции применяются, когда нужно передать аргумент по ссылке и при этом запретить его изменение. В списке аргументов объявления/определения нужно поставить ключевое слово const перед соответствующим аргументом. В списке аргументов объявления/определения нужно поставить ключевое слово const перед соответствующим аргументом. Пример: void aFunc(int& a, const int& b); // прототип функции int main() { int alpha = 7; int beta = 11; aFunc(alpha, beta); return 0; } void aFunc(int& a, const int& b) // определение функции { a = 107; // корректно b = 111; /* ошибка при попытке изменить кон‐ стантный аргумент*/ }

 

 

9. Перегруженные функции. Встраиваемые функции. Рекурсивные функции. Перегруженные функции — это функции с одним именем, но с разными типами аргументов. Их используют, когда несколько функций выполняют одинаковые действия, только над разными типами. Перегруженные функции могут отличаться не только типами аргументов, но и их количеством, но они должны возвращать значение одного типа. Пример #include <iostream> #include <cmath> using namespace std; int summa(int& a, int& b) { cout << "Складываем два целых числа "; return a+b; } int summa(int& a, int& b, int&c) { cout << "Складываем три целых числа "; return a+b+c; } int summa(float& a, float& b) { cout << "Складываем два дробных числа "; return floor(a+b); } //выделение целой части int main() { int a, b, c; float d, e; cout << "Введите два целых числа "; cin >> a >> b; cout << a <<" + "<< b <<" = "<< summa(a,b) << endl; cout << "Введите еще одно целое число "; cin >> c; cout << a <<" + "<< b <<" + "<< c <<" = "<< summa(a,b,c) <<endl; cout << "Введите два дробных числа "; cin >> d >> e; cout << d <<" + "<< e <<" = "<< summa(d,e) << endl; return 0; } Рекурсивные функции. Ситуацию, когда функция тем или иным образом вызывает саму себя, называют рекурсией. Рекурсия, когда функция обращается сама к себе непосредственно, называется прямой; в противном случае она называется косвенной. Все функции языка С++ (кроме функции main) могут быть использованы для построения рекурсии. В рекурсивной функции обязательно должно присутствовать хотя бы одно условие, при выполнении которого последовательность рекурсивных вызовов должна быть прекращена. Рекурсивные функции обычно выполняются медленнее, чем их нерекурсивные (итеративные) аналоги. Это связано с затратами времени на вызов функции. Однако, как правило, они компактнее и понятнее. Пример. #include <iostream> long factor (int n) {if (n<1) return 1; else return n*fact(n-1); int main() {std::cout<< "Факториал числа 5 равен " << factor(5) << std::endl; return 0;} Встраиваемые
Функция, определенная в теле объявления класса, является встроенной. Встраиваемые функции нужны для сокращения времени работы программы. Пример #include <iostream> using namespace std; inline float sum_cvad(float x = 0.0F,float y = 0.0F) {return (x * x + y * y);} int main() {float a, b; cout «"Введите два числа "; cin » a » b; cout «"a^2 + b^2 = " «sum_cvad(a,b) «endl; cout «"a^2 = " «sum_cvad(a) «endl; /*верно, т.к. по умолчанию второй аргумент равен нулю.*/ return 0; }

 

 

10.Область видимости и класс памяти. У каждой функции есть своя область видимости. В область видимости функции входят все глобальные переменные и переменные, объявленные в этой функ- ции. Глобальные переменные — это переменные, которые определены за пределами любой функции. Глобальные переменные существуют с того момента как они встретились в коде и до конца программы. Если глобальную переменную объявить после какой-нибудь функции, то в этой функции данную переменную нельзя будет использовать. Локальные переменные объявлены внутри функций и видны только в них самих. Обычные локальные переменные, когда функция завершается, уничтожаются. При каждом выполнении функции они создаются заново. Статические переменные определяются только один раз — когда функция вызывается в первый раз. Когда функция заканчивает выполнение операторов, статические переменные остаются в па- мяти. Когда функция снова вызывается, она продолжает их использовать. Например, в листинге 1 есть две локальные переменные а, одна принадлежит функции main, другая — pass_by_value. #include <iostream> using namespace std; void pass_by_value (int a) {a ++; cout<<"В функции pass_by_value a = " << a << endl; } void pass_by_pointer (int* a) {*a +=2; cout << "В функции pass_by_pointer a = " << *a << endl; } void pass_by_reference (int& a) {a +=3; cout << "В функции pass_by_reference a = " << a << endl; } int main() {int a; cout << "Введите перевенную "; cin >> a; cout << "Вы ввели " << a << endl; pass_by_value (a); cout << "Сейчас в функции main переменная a = " << a << endl; pass_by_pointer (&a); cout << "Сейчас в функции main переменная a = " << a << endl; pass_by_reference (a); cout << "Сейчас в функции main переменная a = " << a << endl; return 0; } 11.Объявление и инициализация одномерного и многомерного массива. Работа с элементами массива через указатель Массив – это набор переменных одного типа, имеющих одно и то же имя. Доступ к конкретному элементу массива осуществляется с помощью индекса. В языке С все массивы располагаются в отдельной непрерывной области памяти. Первый элемент массива располагается по самому меньшему адресу, а последний – по самому большому. Массивы могут быть одномерными и многомерными.Общая форма объявления одномерного массива имеет следующий вид:тип имя_переменной [размер]; Инициализация: int mas={1, 2, 3, 4, 5} Объявление многомерного массива: const unsigned int DIM1 = 3;const unsigned int DIM2 = 5;int ary[DIM1][DIM2]; Инициализация многомерного массива: const unsigned int DIM1 = 3;const unsigned int DIM2 = 5;int ary[DIM1][DIM2] = {{ 1, 2, 3, 4, 5 },{ 2, 4, 6, 8, 10 },{ 3, 6, 9, 12, 15 }}; Работа с элементами массива через указатели Допустим, что ptr_ar указывает на первый элемент массива array. Тогда для работы с элементами массива можно пользоваться следующей записью:int *ptr_ar = array; ptr_ar[0] = 10; ptr_ar[1] = 20;т.е. доступ к элементам массива осуществляется по его индексу.

 

12. Передача массивов в функцию. Возвращение массива функцией. Чтобы передать массив в функцию, ей надо сообщить адрес начала массива и количество его элементов. Это можно сделать при помощи двух параметров. Пример. Определить функцию, которая возвращает сумму всех элементов массива. void display(int num[10]) { int i; for (i=0; i<< num[i]; } Когда параметром является двумерный массив, его вторая размерность обязательно указывается в объявлении функции float a[ ][4] Объявление параметра как float a[ ][ ] недопустимо. Нет ничего странного в том, что компилятору требуется вторая размерность, ведь именно она определяет размер тех одномерных массивов, которые составляют двумерный. Пример. Определить функцию, которая распечатывает двумерный массив а[3][4] в виде матрицы. void print (float a[] [4], int n) { for (int i = 0; i < n; i++) {for (int j = 0; j < 4; j++) cout «a[i][j] «" "; cout «endl;}} Дело в том что в C++ в функцию можно передать только указатель (или ссылку) на массив, соответственно вы всегда будете работать с исходным массивом, а не с его копией (и вернете также указатель на исходный массив): int* Func(int *Array) {for(i = 0; i < 3; i++) {Array[i]++;} return Array;} int func(int i, int * mas_old, int * mas_new); int main() {int mas1[]={1, 2, 3, 4}; int mas2[4]; func(4, mas1, mas2); return 0;}

13. Принципы объекто-ориентированного программирования. Инкапсуляция.Наследование.Полипорфизм. Объектно-ориентированное программирование строится на 3-ех принципах: Инкапсуляция Наследование Полипорфизм Инкапсуляция: Проектирование программных и техниче­ских систем базируется на том условии, что никакая подсистема данного уровня не должна зависеть от устройства любой другой подсистемы этого уровня. Такая независимость внутреннего уст­ройства одного объекта от внутреннего устройства другого называ­ется инкапсуляцией. В объектно-ориентированном программировании принцип ин­капсуляции используется для изоляции класса от остальных частей программы, чтобы сделать его самодостаточным для решения кон­кретной задачи. 1.Инкапсуляция в ООП – сосредоточение и сокрытие атрибутов и методов в классе или объекте. Можно осуществлять на 2-х уровнях – класса и объекта. 2. Смысл: инкапсуляция означает, что реализация атрибутов и методов скрыта от пользователя объекта или класса. 3. Цель: организовать доступ пользователя к атрибутам и методам так, чтобы предотвратить несанкционированное использование. 4. Инкапсуляция является развитием принципа модульности в построении ПО. 5. Защита от ошибок программиста заключается в неразрешенных объектах, способах использования методов (атрибутов). 6. Сокрытие позволяет программисту изменять реализацию класса, не изменяя его возможностей для пользователя (не менять интерфейс). 7. Развитие методов модульного программирования. 8. К переменной определенного типа нельзя применять действия, непредусмотренные этим типом; правила видимости типов; Скрывать можно и атрибуты, и методы. Пример class A {public: int a, b; //данные открытого интерфейса int ReturnSomething(); //метод открытого интерфейса private: int Aa, Ab; //скрытые данные void DoSomething();}; //скрытый метод //наряду с private и public есть еще protected Наследование: Принцип наследования оперирует с понятиями «предок - потомок» и предусматривает расширение набора свойств наследника за счет принятия всех свойств предка. Любой класс может быть порожден от другого класса. Для это­го при его объявлении указывается имя класса-родителя. сlass Имя: МодификаторДоступа ИмяБазовогоКласса Порожденный класс автоматически наследует поля, методы и свойства своего родителя и может добавлять их новыми. Таким образом, принцип наследования обеспечивает поэтапное создание сложных классов и разработку собственных библиотек классов. При общем наследовании порожденный класс имеет доступ к наследуемым членам базового класса с видимостью public и protected. Члены базового класса с видимостью private – недоступны. Пример class A{}; class B: public A //класс B наследуется из класса A {}; A obj1; //obj1 есть объект класса A B obj2; //obj2 есть объект класса B void main(){return;}

Полипорфизм: Полиморфизм — термин, используемый для описания процесса, при котором различные реализации функций могут быть доступны с использованием одного имени. Это означает, что основной класс операций может быть оформлен в одном стиле, хотя конкретные действия могут быть различны. В С++ полиморфизм поддерживается и во время компиляции — перегрузка функций и операторов, и во время выполнения программы — использование указателей на базовые классы и виртуальных функций. (Полиморфизм - это когда наследуемые классы или просто различные классы имеют одинаковые методы, но с различной реализацией) Целью полиморфизма является использование одного имени для задания общих для класса действий, причем каждый объект или класс иерархии имеет возможность по-своему реализовать это действие своим собственным, подходящим для него, кодом. Таким образом, полиморфизм является свойством классов решать схожие по смыслу проблемы разными способами./*КЛАСС-РОДИТЕЛЬ*/class Mammal{public: virtual void Speak() {cout<<"Mammal Speakn";} };//Виртуальный метод. Звук неизвестного млекопитающего/*СОЗДАЕМ ПОДКЛАСС МЛЕКОПИТАЮЩЕГО*/ class Dog:public Mammal{ public: void Speak() {cout<<"GavGavn";} };//Виртуальный метод. Собака лает /*СОЗДАЕМ ПОДКЛАСС МЛЕКОПИТАЮЩЕГО*/class Cat:public Mammal {public: void Speak() {cout<<"Meown";} };//Виртуальный метод. Кот мяукает/*СОЗДАЕМ ПОДКЛАСС МЛЕКОПИТАЮЩЕГО*/class Pig:public Mammal {public:void Speak() {cout<<"HruHrun";} }; //Виртуальный метод. Свинья хрюкает

 


14. Класс и объекты в языке С++. Члены класса. Определение класса (поля, методы, доступ к членам класса). Определение методов в классе и вне класса. Определение класса (поля, методы, доступ к членам класса). Классы являются основой С++. Для того чтобы определить объект, нужно сначала определить его форму с помощью ключевого слова class. Объект находится в таком же отношении к своему классу, в каком переменная находится по отношению к своему типу. Объект является экземпляром класса, так же, как и автомобиль — колесного средства передвижения. Класс может содержать приватную часть (private) и общую (public). Приватные элементы не могут использоваться никакими функциями, не являющимися членами класса. Также можно определить и приватные функции, которые могут вызываться только другими функциями — членами класса. Это — один из путей реализации принципа инкапсуляции. По умолчанию все элементы класса приватные, поэтому ключевое слово private можно опустить. Поле класса — это данные, содержащиеся внутри класса. Методы класса — это функции, входящие в состав класса:

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

// детали изделия в качестве объектов #include <iostream> using namespace std; class part // определение класса { private: int modelnumber; // номер изделия int partnumber; // номер детали float cost; // стоимость детали public: // установка данных void setpart(int mn, int pn, float c) { modelnumber = mn; partnumber = pn; cost = c; } void showpart() // вывод данных { cout << "модель " << modelnumber; cout << ", деталь " << partnumber; cout << ", стоимость $" << cost << endl; } }; int main() { part part1; // определение объекта // класса part part1.setpart(6244, 373, 217.55F); // вызов метода part1.showpart(); // вызов метода return 0; } Результат: Модель 6244, деталь 373, цена $217.55

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

Символ (::) является знаком операции глобального разрешения. А имя класса, операция разрешения и имя функции вместе называют — квалификационным именем функции.

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

class OBJ { int i; public: void set_i(int x) {i=x;} void out_i{cout<<i<<endl;}};

void my_function(OBJ x); // прототип int main(void) { OBJ A; A.set_i(10); my_function(A); A.out_i(); return 0; }

void my_function(OBJ x) { x. out_i(); // вывод x = 10 x. set_i(100);// изменение x x. out_i();}// вывод x=100

 

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

15.Конструкторы и деструкторы. Конструктор копирования по умолчанию. Конструкторы и деструкторы. Необходимость инициализации является общим требованием, поэтому С++ предоставляет возможность делать это автоматически при объявлении объекта. Эта автоматическая инициализация реализуется использованием функции, называемой конструктором. Конструктор — специальная функция, являющаяся членом класса и имеющая то же имя. Наиболее часто возлагаемая на конструктор задача — это инициализация полей объекта касса. Однако инициализация не проводится в теле конструктора. Инициализирующее значение расположено в скобках после имени поля. И если необходимо инициализировать сразу несколько полей, то значения разделяются запятыми и образуется список инициализации: someClass(): m1(0), m2(10) {/*пустое тело*/} Нельзя вызывать функцию конструктора в явном виде. Она может иметь параметры, может быть перегруженной. Если в классе не объявлен ни один конструктор, то компилятор сам создает конструктор класса. Во время создания объекта, при выделении памяти вызывается конструктор, а для освобождения памяти из-под объекта, т. е. при прекращении действия объекта, выполняется деструктор. Он имеет такое же имя, как и класс, и перед ним ставится знак тильды (~). Важно запомнить: -конструктор и деструктор, мы всегда объявляем в разделе public; -при объявлении конструктора, тип данных возвращаемого значения не указывается, в том числе — void!!!; -у деструктора также нет типа данных для возвращаемого значения, к тому же деструктору нельзя передавать никаких параметров; -имя класса и конструктора должно быть идентично; -имя деструктора идентично имени конструктора, но с приставкой ~; В классе допустимо создавать несколько конструкторов, если это необходимо. Имена, согласно пункту 2 нашего списка, будут одинаковыми. Компилятор будет их различать по передаваемым параметрам (как при перегрузке функций). Если мы не передаем в конструктор параметры, он считается конструктором по умолчанию; Обратите внимание на то, что в классе может быть объявлен только один деструктор; # include <iostream> using namespace std; class AB //класс{ private: int a; int b; public:AB(int A, int B) //эти параметры мы передадим при создании объекта в main{a = A;//присвоим нашим элементам класса значения параметровb = B;cout << "Тут сработал конструктор, который принимает параметры: " << endl;//и здесь же их отобразим на экранcout << "a = " << a << endl;cout << "b = " << b << endl << endl;} void setAB(){cout << "Введите целое число а: ";cin >> a;cout << "Введите целое число b: ";cin >> b;} void getAB(){cout << "a = " << a << endl;cout << "b = " << b << endl << endl;}~AB() // это деструктор. не будем заставлять его чистить память, пусть просто покажет где он сработал{cout << "Тут сработал деструктор" << endl;}}; int main(){ setlocale (LC_ALL, "rus"); AB obj1(100, 100); //передаем конструктору параметрыobj1.setAB(); //присвоим новые значения переменнымobj1.getAB(); //и выведем их на экранAB obj2(200, 200);} //передаем конструктору параметрыХочется еще добавить, что, как и обычным функциям, мы можем передавать конструктору параметры. Через параметры, конструктору можно передавать любые данные, которые будут необходимы при инициализации объектов класса.Деструктор срабатывает в тот момент, когда завершается работа программы и уничтожаются все данные.

Конструктор копирования по умолчанию. Такой конструктор представляется компилятором для каждого создаваемого класса и называется копирующим конструктором по умолчанию. Этот конструктор имеет единственный аргумент, являющийся объектом того же класса, что и конструктор: имя_класса(const Имя_класса &). Конструктор копирования создается всякий раз, когда создается новый объект и в качестве его значения выбирается существующий объект того же самого типа. Пусть у нас имеются инициализированный объект класса myClass obj1. Тогда, определив еще два объекта класса myClass, мы можем инициализировать их следующим образом: myClass obj2(obj1);myClass obj3 = obj1. В обоих случаях вызывается конструктор копирования по умолчанию, действия которого сводятся к копированию значений полей объекта obj



Поделиться:




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

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


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