Наследование
Наследование обозначает такое отношение между классами, когда один класс использует структурную или функциональную часть одного или нескольких классов (соответственно простое и множественное наследование).
Наследование является иерархической системой, позволяющей лучше выразить взаимодействия между классами. Иерархия представляет собой вид отношений подчинённости типа: принадлежности частного общему.
Когда мы говорим, что нечто является видом чего-либо, мы подразумеваем большую детализацию.
В С++ иерархичность реализована в концепции классов — когда один класс может наследовать или происходить от класса более высокого уровня. В наследовании классов реализуются принципы их иерархической подчинённости.
Если объявляется наследуемый класс, то базовый класс должен быть описан выше, иначе компилятор сгенерирует ошибку.
Синтаксис : (открытое наследование):
Class имя_класса :< режим доступа> имя_базового_класса.
В описании базового класса появляется новое слово:protected, так как данные под словом private не доступны для наследования.
Какой бы доступ не был определён для наследования данные, описанные в базовом классе как private не доступны для производного класса.
#include <iostream.h>
class base
{ int x;
public:
void setx(int n){x=n;}
void prinx(){cout<<"x="<<x<<"\n";}
};
class deriv : private base
{
int y;
public:
void setxy(int n,int m){setx(n);y=m;}
void prinxy(){prinx();cout<<"y="<<y<<"\n";}
};
void main(void)
{
deriv ob;
cout <<"результат работы программы: \n" ;
ob.setxy(10,25);
ob.prinxy();
}
Результат работы программы:
x=10
y=25
Инициализация наследуемых классов
Все действия по инициализации объектов выполняет конструктор порождённого класса.
Если конструктору базового класса требуются аргументы, то они должны быть указаны в списке аргументов конструктора. В общем виде конструктор имеет вид:
Конструктор_производного_класса(список аргументов): базовый_класс1( список аргументов)…базовый_класс_N (список аргументов) { тело конструктора}
Производный класс может иметь не один , а несколько базовых. В этом случае базовые классы указываются списком.
#include <iostream.h>
class B1
{ public:
B1(){cout<<"работа конструктора B1\n";}
~B1(){cout<<" работа деструктора B1\n";}
};
class B2
{ public:
B2(){cout<<"работа конструктора B2\n";}
~B2(){cout<<" работа деструктора B2\n";}
};
class D:public B1,public B2
{
public:
D(){cout<<"работа конструктора D\n";}
~D(){cout<<" работа деструктора D\n";}
};
void main(void)
{
cout <<"результат работы программы: \n" ;
D ob;
cout<<"*********************\n" ;
}
Результат работы программы:
работа конструктора B1
работа конструктора B2
работа конструктора D
*********************
работа деструктора D
работа деструктора B2
работа деструктора B1
Конструкторы базового класса должны быть объявлены с атрибутами protected или public для того, чтобы обеспечить возможность их вызова из класса-наследника.
Потоки
Классы ввода-вывода iostream рассматривают информацию, как побитовый поток данных. Если данные выводятся на экран или заносятся в файл, то источник их как правила находится в программе. Если поток направлен в противоположную сторону, то данные могут поступать либо с клавиатуры или из файла, В этом случае они заносятся в переменные.
Операция записи на диск достаточно временноёмка, поэтому используют буфер обмена.
В С++ используется ОО подход к реализации обмена данными с буферными потоками.
- Класс streambuf управляет буфером, его методы позволяют наполнить, опорожнить и очистить буфер.
- Класс ios является базовым для классов ввода-вывода.
- Классы istream и ostream являются произвольными от класса ios и отвечают соответственно за потоковый ввод и вывод данных.
- Класс iosteam является произвольным от istream и ostream и обеспечивает методы ввода-вывода для печати на экран.
- Классы fstream используются для ввода-вывода из файла.
В файле iostream.h определены классы iostream и ostream, именно то, что эти операторы ввода-вывода работают с классами, позволяет перегружать их для работы с классами пользователя. Оператор cin является глобальным объектом и перегружается таким образом, что можно вводить различные типы данных.
В частности при помощи этого объекта модно ввести тип *char, то есть строку символов. Можно использовать дополнительные методы этого класса, что бы более полно контролировать ввод-вывод. Пример : ввод одного символа можно реализовать при помощи метода cin.get()>>
#include <iostream.h>
#include <math.h>
int main(void)
{
char ch;
while((ch=cin.get())!=EOF)
{
cout << "ch: "<<ch<<endl;
}
cout <<"\n конец \n";
return 0;
} //ввод EOF — Ctrl+Z
cin.get() возвращает не объект типа iostream, а тип int. А если вы используете параметр cin.get(a), то возвращается объект iostream, а параметру присваивается значение из потока. Для работы со строками подойдёт как оператор ввода <<, так и методы get() и getline(). Для ввода строки можно использовать get() и getline() с тремя параметрами:
- указатель на массив символов.
- максимально-возможное количество символов в строке, включая концевой символ;
- разделитель строк.
cin.get(str,80,”\n”);
Разница между этими двумя функциями в том, что первая оставляет символ разделения строк в буфере , а вторая удаляет его.
Существует ещё несколько дополнительных методов:
Ignore(80,”\n”) параметры — сколько пропускается символов без чтения и разделитель.
Peek() — просматривает, но не считывает очередной символ.
Putback() —вставляет символ в поток ввода.
#include <iostream.h>
#include <iomanip.h>
int main(void)
{
char ch;
cout <<"введите фразу: ";
while(cin.get(ch))
{
if(ch=='!') cin.putback('$');
else cout <<ch;
while(cin.peek()=='#')
cin.ignore(1,'\n');
}
return 0;
}
Результат работы программы:
введите фразу: кен!!gh#ghj##sdfdgfh
// кен$$ghghjsdfdgfh
Для объекта cout существуют соответствующие методы put() и write().
Cout.put() и cout.write(мах. Размер вывода);
Кроме этого существуют так называемые флаги и манипуляторы для форматированного ввода.
Cout.Width() — устанавливается точное значение ширины поля ввода.
Cout.fill(‘*’) — заполнение пустых позиций поля * (можно другой символ).
Флаги позволяют оформить вывод:
Управление выводом данных
- \n— новая строка.
- \t—табуляция (несколько пробелов).
- \\— обратный слеш.
- \a—звуковой сигнал.
Манипуляторы, не требующие включения файла iomanip.h:
- flush—очищает буфер ввода
- endl —вводит конец строки
- oct —8- ричное представление числа
- dec —10- ричное представление числа
- hex —16- ричное представление числа
Манипуляторы, требующие включения файла iomanip.h:
- setw(ширина) —ширина поля вывода.
- setfill(символ) —символ заполнения пустых позиций.
- setprecision (точность) —количество знаков после ,.
Все манипуляторы, кроме flush, end, setw() остаются включенными на протяжении работы всей программы, если не будет других установок.
Флаги используют формат написания setf(ios::флаг1 | ios::флаг2).