Содержание
- 2. Массивы Классы и объекты ООП Если в классе определен конструктор с параметрами, каждый объект в массиве
- 3. Массивы Классы и объекты ООП Если конструктор объекта имеет несколько аргументов, следует применять полную форму инициализации.
- 4. Массивы Классы и объекты ООП Инициализированные и неинициализированные массивы class cl { int i ; public:
- 5. Массивы Классы и объекты ООП Пример: создание двумерного массива объектов и инициализация его: // Создание двумерного
- 6. Указатели. Указатели на объекты Классы и объекты ООП #include using namespace std; class cl { int
- 7. Указатели. Указатели на объекты Классы и объекты ООП #include using namespace std; class cl { int
- 8. Указатели. Проверка типа указателей Классы и объекты ООП С++ содержит специальный указатель this. Это указатель, который
- 9. Указатели. Указатель this Классы и объекты ООП При вызове функции-члена ей неявно передается указатель на вызывающий
- 10. Указатели. Указатель this Классы и объекты ООП На самом деле обычно конструктор таким образом не пишут,
- 11. Указатели. Указатели на производные типы Классы и объекты ООП Как правило, указатель одного типа не может
- 12. Указатели. Указатели на производные типы Классы и объекты ООП Рассмотрим программу: применение указателя на базовый класс
- 13. Указатели. Указатели на члены класса Классы и объекты ООП В языке С++ существует особый тип указателя,
- 14. Указатели. Указатели на члены класса Классы и объекты ООП Пример: #include using namespace std; class cl
- 15. Указатели. Указатели на члены класса Классы и объекты ООП #include using namespace std; class cl {
- 16. Указатели. Указатели на члены класса Классы и объекты ООП Указатели на члены класса отличаются от указателей
- 17. Структуры данных Стек (stack) Стеки – последовательный список переменной длины, включение и исключение элементов из которого
- 18. Структуры данных C / С++ Стек (stack) int stack [MAX]; int tos=0; // вершина стека void
- 19. Классы и объекты #include #define SIZE 100 // Определение класса stack class stack { int stck[SIZE];
- 20. #include struct stack // Описание элемента стека { int value; struct stack *next; /* значение, следующий
- 22. Скачать презентацию
Массивы
Классы и объекты
ООП
Если в классе определен конструктор с параметрами, каждый объект
Массивы
Классы и объекты
ООП
Если в классе определен конструктор с параметрами, каждый объект
Вот как выглядит слегка измененная версия предыдущей программы:
#include Фактически список инициализации, показанный в этой программе, является сокращенным вариантом более сложной формы:
using namespace std;
class cl
{
int i ;
public:
cl(int j) { i=j; } // Конструктор int
get_i() { return i; }
};
int main() {
// Список инициализации
cl ob[3] = {1, 2, 3};
int i ;
for(i=0; i<3; i++)
cout << ob[i].get_i() <<"\n";
return 0; }
// программа выводит числа 1, 2 и 3.
cl ob[3] = { cl(1), cl(2), сl(3) };
Здесь конструктор cl вызывается явно. Разумеется, короткая форма инициализации используется чаще. В основе этого способа лежит возможность автоматического преобразования типа, если конструктор имеет только один аргумент. Таким образом, сокращенную форму инициализации можно использовать, только если массив состоит из объектов, конструкторы которых имеют лишь один аргумент.
Массивы
Классы и объекты
ООП
Если конструктор объекта имеет несколько аргументов, следует применять полную
Массивы
Классы и объекты
ООП
Если конструктор объекта имеет несколько аргументов, следует применять полную
#include Здесь конструктор массива cl имеет два аргумента. Следовательно, следует применять не сокращенную, а полную форму инициализации.
using namespace std;
class cl
{
int h, i;
public:
// Конструктор с двумя параметрами
cl (int j, int k) { h=j; i=k; }
int get_i() { return i; }
int get_h() { return h; }
};
int main() {
// Инициализация
cl ob[3] = {cl(l, 2), cl(3, 4), cl(5, 6) };
int i ;
for(i=0; i<3; i++)
{ cout << ob[i].get_h();
cout << ", ";
cout << ob[i].get_i() << "\n";
}
return 0; }
Массивы
Классы и объекты
ООП
Инициализированные и неинициализированные массивы
class cl {
int i ;
Массивы
Классы и объекты
ООП
Инициализированные и неинициализированные массивы
class cl {
int i ;
cl (int j) // Конструктор
{ i=j; }
int get_i() { return i; }
};
cl а[9]; // Ошибка, конструктору необходим список инициализации
Этот оператор не работает, поскольку предполагается, что класс cl не имеет параметров, так как в объявлении массива не указан список инициализации. Однако класс cl не содержит конструкторов, не имеющих параметров. Итак, поскольку данному объявлению не соответствует ни один конструктор, компилятор выдаст сообщение об ошибке. Чтобы решить эту проблему, необходимо перегрузить конструктор, добавив вариант, не имеющий параметров, как показано ниже. Теперь в программе можно объявить оба вида массива:
Особая ситуация возникает, когда необходимо создать как инициализированные, так и неинициализированные массивы объектов. Рассмотрим следующий класс:
Здесь в классе cl определен конструктор с одним параметром. Это значит, что любой массив такого типа должен быть инициализирован.
Т.о. массив нельзя объявить обычным образом:
class cl {
int i; public:
cl() {i=0;} // для неинициализированных массивов
cl(int j) { i=j; } // для инициализированных массивов
int get_i() { return i; }
};
В таком варианте программы допускаются следующие операторы:
// Инициализированный массив
cl a1[3] = {3, 5, 6};
// Неинициализированный массив
cl а2[34];
Массивы
Классы и объекты
ООП
Пример: создание двумерного массива объектов и инициализация его:
//
Массивы
Классы и объекты
ООП
Пример: создание двумерного массива объектов и инициализация его:
//
#include
using namespace std;
class samp {
int a; public:
samp(int n) { a = n; }
int get_a() { return a; }
};
int main ()
{
samp ob[4][2] = {1,2,3,4,5,6,7, 8 };
int i;
for(i=0; i<4; i++)
{
cout << ob[i][0].get_a() << ' ';
cout << ob[i][1].get_a() << "\n";
}
cout << "\n"; return 0;
}
программа выводит на экран:
1 2
3 4
5 6
7 8
Указатели. Указатели на объекты
Классы и объекты
ООП
#include
using namespace std;
Указатели. Указатели на объекты
Классы и объекты
ООП
#include
using namespace std;
{
int i ;
public:
cl(int j) { i=j; }
int get_i() { return i; }
};
int main()
{
cl ob(88), *p;
р = &ob; // Получаем адрес объекта ob
cout << p->get_i();
// для вызова функции get_i() применяется
// оператор ->
return 0;
}
Указатели могут ссылаться не только на переменные встроенных типов, но и на объекты. Для доступа к членам класса через указатель на объект используется оператор "->", а не ".".
Пример:
При увеличении указателя на единицу он перемещается на следующий элемент того же типа. Например, целочисленный указатель будет ссылаться на следующее целое число. Как правило, адресная арифметика зависит от типа указателя, т.е. она зависит от типа данных, на который ссылается указатель.
Это правило касается и указателей на объекты.
Указатели. Указатели на объекты
Классы и объекты
ООП
#include
using namespace
Указатели. Указатели на объекты
Классы и объекты
ООП
#include
using namespace
class cl {
int i ; public:
cl() { i=0; } cl(int j) { i=j; }
int get_i() { return i; }
};
int main()
{
cl ob[3] = {1, 2, 3}; cl *p; int i ;
p = ob; // Установить указатель на первый элемент массива
for(i=0; i<3; i++)
{ cout << p->get_i() << "\n";
p++; // Указатель на следующий объект
}
return 0;
}
Пример: присваивание указателю адреса открытого члена объекта и ссылка на этот член с его помощью.
#include Пример: использование указателя для доступа ко всем трем элементам массива ob.
using namespace std;
class cl
{ public: int i ;
cl(int j) { i=j; }
};
int main() {
cl ob(1); int *p;
р = &ob.i; // Получить адрес члена ob.i
cout << *р; // Обращение к члену ob.i // через указатель р
return 0;
}
Указатель р ссылается на целое число, он имеет тип int. В данном случае не имеет значения, что переменная i является членом объекта ob.
Указатели. Проверка типа указателей
Классы и объекты
ООП
С++ содержит специальный указатель this.
Указатели. Проверка типа указателей
Классы и объекты
ООП
С++ содержит специальный указатель this.
Например:
ob fl(); // предположим, что ob ‒ это объект, функции fl() автоматически передается указатель на объект ob. Этот указатель и называется this.
Важно понимать, что указатель this передается только функциям-членам. Дружественным функциям указатель this не передается.
Работая с указателями, следует иметь в виду: присваивать можно лишь указатели совместимых типов.
int *pi;
float *pf;
Следующий оператор неверен:
pi = pf; // Ошибка ‒ несовместимость типов.
Разумеется, любую несовместимость можно преодолеть, используя приведение типов, однако это нарушает принципы строгой проверки типов.
Указатель this
Указатели. Указатель this
Классы и объекты
ООП
При вызове функции-члена ей неявно
Указатели. Указатель this
Классы и объекты
ООП
При вызове функции-члена ей неявно
#include int main() продолжение Внутри класса к функции-члену можно обращаться напрямую, не используя объекты и название класса. Таким образом, внутри конструктора pwr() оператор b = base; (сокращённая форма) означает, что переменной b, принадлежащей вызывающему объекту, присваивается значение переменной base.
using namespace std;
class pwr
{
double b;
int e ;
double val;
public:
pwr(double base, int exp);
double get_pwr() { return val; }
};
pwr::pwr(double base, int exp)
{
b = base;
e = exp;
val = 1;
if(exp==0) return;
for( ; exp>0;
exp -> val = val * b;
} см.продолжение
{ pwr x(4.0, 2), y(2.5, 1), z(5.7, 0);
cout << x.get_pwr() << " ";
cout << y.get_pwr() << " ";
cout << z.get_pwr() << "\n";
return 0; }
Однако тот же самый оператор можно переписать иначе (в расширенной форме):
this -> b = base;
Указатель this ссылается на объект, вызывающий функцию pwr(). Т.о., выражение this->b ссылается на переменную b, принадлежащую текущему объекту. Например, если функция pwr() вызвана объектом х (в объявлении х(4.0, 2)), то указатель this в предыдущем операторе будет ссылаться на объект х. Впрочем, этот оператор можно записать в сокращенном виде, не используя указатель this.
Указатели. Указатель this
Классы и объекты
ООП
На самом деле обычно конструктор
Указатели. Указатель this
Классы и объекты
ООП
На самом деле обычно конструктор
Следует помнить, что указатель this автоматически передается всем функциям-членам. Следовательно, функцию get_pwr() можно переписать иначе:
double get_pwr() { return this->val; }
В этом случае, если функция get_pwr() вызывается с помощью оператора
y.get_pwr () ;
указатель this будет ссылаться на объект у.
Рассмотрим полное определение конструктора pwr(), написанное с помощью указателя this:
pwr::pwr (double base, int exp)
{
this->b = base;
this->e = exp;
this->val = 1;
if(exp==0) return;
for( , exp>0; exp--)
this -> val = this -> val * this -> b;
}
Сокращённая форма
(с предыдущего слайда)
pwr::pwr(double base, int exp)
{
b = base;
e = exp;
val = 1;
if(exp==0) return;
for( ; exp>0;
exp -> val = val * b;
}
Указатели. Указатели на производные типы
Классы и объекты
ООП
Как правило, указатель одного
Указатели. Указатели на производные типы
Классы и объекты
ООП
Как правило, указатель одного
Однако у этого правила есть важное исключение, касающееся производных классов:
Предположим для начала, что в программе объявлены два класса: B и D. Кроме того, допустим, что класс D является производным от базового класса B. В этом случае указатель типа B* может ссылаться и на объекты типа D.
В принципе, указатель на базовый класс можно использовать как указатель на объект любого производного класса.
Однако обратное утверждение неверно. Указатель типа D* не может ссылаться на объекты класса B.
Кроме того, с помощью указателя на базовый класс можно ссылаться только на наследуемые члены, но не на новые члены производного класса. (Однако указатель на базовый класс можно привести к типу указателя на производный класс и получить доступ ко всем членам производного класса.)
Указатели. Указатели на производные типы
Классы и объекты
ООП
Рассмотрим программу: применение указателя
Указатели. Указатели на производные типы
Классы и объекты
ООП
Рассмотрим программу: применение указателя
#include продолжение Как видим, указатель на базовый класс позволяет обращаться к объекту производного класса.
using namespace std;
class base
{
int i ;
public:
void set_i(int num) { i=num; }
int get_i() { return i; }
};
class derived: public base
{
int j ;
public:
void set_j(int num) { j=num; }
int get_j() { return j; }
};
см.продолжение
int main()
{
base *bp;
derived d;
bp = &d; /* Базовый указатель ссылается на объект производного класса */
// Доступ к объекту производного класса с
// помощью указателя на производный класс
bp -> set_i(10);
cout << bp ->get_i () << " ";
/* Следующий оператор не работает. На элементы производного класса нельзя ссылаться с помощью указателя на базовый класс
bp -> set_j(88); // Ошибка
cout << bp -> get_j(); // Ошибка
*/
return 0;
}
Указатели. Указатели на члены класса
Классы и объекты
ООП
В языке С++ существует
Указатели. Указатели на члены класса
Классы и объекты
ООП
В языке С++ существует
Указатель такого вида называется указателем на член класса.
Этот необычный указатель задает смещение внутри объекта соответствующего класса.
Поскольку указатели на члены класса не являются указателями в обычном смысле слова, к ним нельзя применять операторы "." и "->".
Чтобы обратиться к члену класса с помощью указателя на него, следует применять особые операторы: ".*" и "->*".
Указатели. Указатели на члены класса
Классы и объекты
ООП
Пример:
#include
using namespace
Указатели. Указатели на члены класса
Классы и объекты
ООП
Пример:
#include
using namespace
class cl
{ public:
сl (int i)
{ val=i; }
int val;
int double_val()
{ return val+val; }
};
int main()
{ int cl::*data; // Указатель на член класса
int(cl::*func)(); //Указатель на функцию-член
cl ob1(1), ob2(2); // Создаем объекты
data = &cl::val; // Определяем смещение члена val
func = &cl::double_val; // Определяем смещение
//функции double_val()
cout << "Значения: ";
cout << ob1.*data << " " << ob2.*data << "\n";
cout << "Удвоенные значения: ";
cout << (ob1.*func) () << " ";
cout << (ob2.*func)() <<"\n";
return 0;
}
Эта программа создает два указателя на члены класса: data и func.
Синтаксические особенности их объявлений: объявляя указатели на члены, следует задавать имя класса и применять оператор разрешения области видимости.
Кроме того, программа создает два объекта класса cl: оb1 и оb2. Указатели на члены класса могут ссылаться как на переменные, так и на члены. Затем вычисляются адреса членов val и double_val (). Эти "адреса" представляют собой смещения соответствующих членов в объекте класса cl. Значения, хранящиеся в переменной val в каждом из объектов, выводятся на экран с помощью указателя data.
В заключение программа вызывает функцию double_func (), используя переменную func, являющуюся указателем на член класса. Обратите внимание на то, что для правильного выполнения оператора ".*" необходимы дополнительные скобки.
Указатели. Указатели на члены класса
Классы и объекты
ООП
#include
using namespace
Указатели. Указатели на члены класса
Классы и объекты
ООП
#include
using namespace
class cl
{ public:
cl (int i)
{ val=i; }
int val;
int double_val()
{ return val+val; }
};
int main() {
int cl::*data; // Указатель на переменную-член int (cl::*func)(); // Указатель на функцию-член cl ob1(1) ob2(2); // Создаем объекты cl *pl, *р2;
pl = &ob1; // Доступ к объекту через указатель
р2 = &ob2;
data = &cl::val; //Определяем смещение переменной val
func = &cl::double_val; // Определяем смещение
// функции double_val()
cout << "Значения: ";
cout << pl ->* data << " " << p2->*data << "\n";
cout << "Удвоенные значения: ";
cout << (pl->*func) << " ";
cout << (p2->*func)() << "\n";
return 0;
}
Для доступа к члену класса через объект или ссылку на него используется оператор ".*". Если задан указатель на объект, для доступа к его членам необходимо применять оператор "->*".
Пример:
В этом варианте программы переменные p1 и р2 являются указателями на объекты класса cl, поэтому для доступа к членам val и double_func () применяется оператор "->*".
Указатели. Указатели на члены класса
Классы и объекты
ООП
Указатели на члены класса
Указатели. Указатели на члены класса
Классы и объекты
ООП
Указатели на члены класса
Рассмотрим фрагмент программы, полагая, что класс cl объявлен, как показано выше:
int cl::*d;
int *p;
cl o;
p = &o.val // Адрес конкретной переменной val
d = &cl::val // Смещение обобщенной переменной val
Здесь указатель р ссылается на целочисленную переменную, принадлежащую конкретному объекту. В то же время переменная d хранит смещение члена val внутри любого объекта класса cl.
Структуры данных
Стек (stack)
Стеки – последовательный список переменной длины, включение и
Структуры данных
Стек (stack)
Стеки – последовательный список переменной длины, включение и
Пример: принцип включения элементов в стек и исключения элементов из стека.
На рисунке изображены состояния стека:
а) пустого;
б-г) после последовательного включения в него элементов с именами 'A', 'B', 'C';
д, е) после последовательного удаления из стека элементов 'C' и 'B';
ж) после включения в стек элемента 'D'.
Основные операции над стеком:
- включение нового элемента (английское название push - заталкивать)
- исключение элемента из стека (англ. pop - выскакивать).
Полезными могут быть также вспомогательные операции:
определение текущего числа элементов в стеке;
очистка стека;
неразрушающее чтение элемента из вершины стека, которое может быть реализовано, как комбинация основных операций: x:=pop(stack); push(stack,x).
И+ПРГ
Структуры данных
C / С++
Стек (stack)
int stack [MAX];
int tos=0; //
Структуры данных
C / С++
Стек (stack)
int stack [MAX];
int tos=0; //
void push (int i)
/* Занесение элемента в стек */
{
if (tos >= MAX)
{
printf (" Стек полон \n");
return 0;
}
// заносим элемент в стек
stack[tos] = i;
tos++;
return 0;
}
Через массив
И+ПРГ
int pop (void)
/* Выборка элемента из стека */
tos--;
if (tos < 0)
{
printf (" Стек пуст \n");
return 0;
}
return stack [tos];
}
Написать головную программу:
Занести в стек 5 элементов
Вывести содержимое стека на экран
Удалить верхний элемент
Удалить второй снизу элемент
Вывести оставшуюся часть стека
Классы и объекты
#include
#define SIZE 100
// Определение класса stack
class stack
{
int
Классы и объекты
#include
#define SIZE 100
// Определение класса stack
class stack
{
int
int tos;
public:
void init ();
void push (int i);
int pop ();
};
//-----------------------------------------------------
void stack :: init () /* :: - оператор разрешения области видимости (доступ к области видимости). Он определяет компилятору, что данная версия функции init() принадлежит классу stack, т.е. находится в области видимости этого класса */
{ tos = 0; }
//-----------------------------------------------------
void stack :: push (int i)
{ if (tos == SIZE)
{ cout << "Стек полон.\n"; return; }
stck[tos] = i;
tos++;
} // см. продолжение
// продолжение
into stack :: pop ()
{ if (tos == 0)
{ cout << "Стек пуст.\n"; return 0; }
tos--;
return stck[tos]; }
int main ()
{ stack stack1, stack2; /* создаем 2 объекта класса stack */
stack1.init (); // Вызов init для объекта stack1
stack2.init (); // Вызов init для объекта stack2
stack1.push (1);
stack2.push (2);
stack1.push (3);
stack2.push (4);
cout << stack1.pop() << " ";
cout << stack1.pop() << " ";
cout << stack2.pop() << " ";
cout << stack2.pop() << " \n ";
return 0;
}
Работа со СТКЕом в ООП через массив
Вывод на экран: 3 1 4 2
ООП
#include
struct stack // Описание элемента стека
{ int value; struct stack
#include
struct stack // Описание элемента стека
{ int value; struct stack
void push(stack* &NEXT, const int VALUE) // Добавить элемент в стек
{ stack *MyStack = new stack;
MyStack->value = VALUE;
MyStack->next = NEXT;
NEXT = MyStack;
}
int pop(stack* &NEXT) // Удалить элемент из стека
{ int temp = NEXT->value;
stack *MyStack = NEXT;
NEXT = NEXT->next;
delete MyStack;
return temp;
}
int main()
{ stack *p=0;
push(p,100);
push(p,200);
cout << pop(p);
cout << pop(p);
return 0;
}
ООП
Работа со СТЕКом в ООП
через указатели и элементы односвязного списка
Структуры данных
C / С++