
- •Void Putdec(int d);
- •Int Numberdec();
- •Int Sprint::Numberdec()
- •Int main(int argc, char* argv[])
- •Void Init(int m,int s, int d);
- •Void Sprint::Init(int m,int s, int d)
- •Void Sprint::Init(int m,int s)
- •Int main(int argc, char* argv[])
- •1. В базовом и производном классе нет конструкторов.
- •Int main(int argc, char* argv[])
- •2. В базовом классе создан конструктор без параметров, в производном конструктор отсутствует.
- •Int main(int argc, char* argv[])
- •3. В базовом классе конструктор отсутстивует, в производном создан без параметров
- •Int main(int argc, char* argv[])
- •4. В базовом и производном классах есть конструкторы без параметров.
- •Int main(int argc, char* argv[])
- •5. В базовом есть конструктор без параметров, в производном с параметрами.
- •Int main(int argc, char* argv[])
- •6. Если в базовом классе есть конструктор с параметрами, в производном классе должен быть с параметрами и базовый конструктор должен быть явно вызван.
- •Int main(int argc, char* argv[])
- •Int main(int argc, char* argv[])
Наследование. Производные классы.
1) Производный класс, наследование полей и методов и добавление новых полей и методов на С++
Имеем класс Record (min,sec), введем новый класс Sprint, учитывающий десятые доли секунды спортсмена, спринтерский бег. (int dec) . В классе добавим метод Putdec , устанавливающий количество десятых долей и Numberdec, вычисляющий общее число десятых долей секунды у объектов (например, для сравнения результатов).
class Record
{
public:
void Init (int m,int s); // задание значений полей
int Numbersec();
private:
int min;
int sec;
};
int Record::Numbersec()
{
return min*60+sec;
}
void Record::Init(int m,int s)
{
min=m;
sec=s;
}
// наследуемый класс
class Sprint : public Record // Sprint-наследник Record
{
public:
// новые методы Sprint
Void Putdec(int d);
Int Numberdec();
private:
// новое поле Sprint
int dec;
};
В класссе Sprint имеются также public методы Numbersec, Init и private поля min, sec.
void Sprint::Putdec(int d)
{
dec=d;
}
int Sprint::Numberdec()
{
int k;
k=Numbersec();
return k*10+dec;
}
int main(int argc, char* argv[])
{
int m,n;
Record x,y;
x.Init(4,36); // min=4 sec=36
y.Init(2,4); // min=2 sec=4
Sprint z;
z.Init(1,8); // min=1 sec=8
z.Putdec(4); // dec=4
m=z.Numberdec(); // m=684
n=z.Nubersec(); // n=68 вызов наследуемого метода
}
2) Модификатор доступа protected
Заменим вызов Numbersec() из Numberdec прямым вычислением:
Int Sprint::Numberdec()
{
int k;
k=min*60+sec; // вместо k=Numbersec();
return k*10+dec;
}
Ошибка! min, sec is not accessible
min , sec определены как private в Record и не могут вызываться из методов другого класса Sprint, даже после наследования.
Исправление:
class Record
{
public:
void Init (int m,int s);
int Numbersec();
protected: // вместо private:
int min;
int sec;
};
К полям и методам из protected могут обращаться как методы Record, так и методы всех наследуемых классов, (Sprint).
class A
{
......
protected:
int x;
....
};
......
class B : public A
{
....
}
class C : public B
{
....
};
Идентификатор x может появиться в любом методе классов A, B, C.
Инкапсуляция: public, private, protected разграничивают доступ к полям и методам.
3) Модификатор в заголовке наследуемого класса
class Sprint : public Record // public - открытое наследование
public означает, что наследуемые поля из Record остаются без изменения:
Record public -> Sprint public
Record protected -> Sprint protected
Record private -> Sprint private
Другие варианты:
class Sprint : protected Record // защищенное наследование
Наследуемые поля и методы перестают быть public
Record public -> Sprint protected
Record protected -> Sprint protected
Record private -> Sprint private
class Sprint : private Record // закрытое наследование
Все наследуемые поля и методы становятся private
Record public -> Sprint private
Record protected -> Sprint private
Record private -> Sprint private
Int main(int argc, char* argv[])
{
int m,n;
Record x;
x.Init(2,8); // правильно Init в Record public
Sprint z;
z.Init(1,8); // min=1 sec=8 // ошибка, Init теперь private
z.Putdec(4); // dec=4 // правильно Putdec определена в Sprint как public
m=z.Numberdec(); // m=684 // правильно
n=z.Nubersec(); // n=68 // ошибка
}
В современных ООП языках используется только открытое наследование
4) Множественное наследование
В C++ класс может быть наследником нескольких классов.
class Record
{
public:
..........
protected:
int min,sec;
...........
}
class Person
{
public:
..........
protected:
char Fam[30];
int Vozrast;
.............
}
class Sportsman : public Person , public Record
{
public:
..........
private:
int Category;
............
}
В классе Sportsman наследуются поля min, sec, Fam,Vozrast.
Пусть в классе Person имеется поле double min.
class Person
{
public:
..........
protected:
char Fam[30];
int Vozrast;
double min;
.............
}
void Sportsman::Putmin(int m)
{
min=m; // какое min из двух ??
......
}
Решение – указывать явно класс. Person::min=m;
В современных языках множественное наследование отсутствует !
5) Наследование на языке java
Наследуемый класс – подкласс (subclass), класс от которого наследуется – суперкласс (superclass).
Смысл prrotected такой же.
Вариант программы с дополнительным классом для задания main.
class Record // это суперкласс
{
protected int min,sec;
public void Init(int m,int s)
{
min=m;
sec=s;
}
public int Numbersec()
{
return min*60+sec;
}
}
class Sprint extends Record // extends наследует (расширяет) – это подкласс
{
private int dec;
public void Putdec(int d)
{
dec=d;
}
public int Numberdec()
{
int k;
k=min*60+sec;
return k*10+dec;
}
}
public class WorkSport // класс для main public!
{
public static void main (String args[] )
{
int p;
Record a=new Record(); // объект Record
a.Init(2, 40);
p=a.Numbersec();
System.out.printf("%d\n ", p);
Sprint b=new Sprint(); // объект Sprint
b.Init(1, 10); // вызов наследуемого метода; b.min=5; - ошибка!
b.Putdec(6);
p=b.Numberdec();
System.out.printf("%d\n ", p);
}
}
На консоли:
160
706
WorkSport содержит единственный метод main. Файл с тремя классами : WorkSport.java!!
Понятие пакета package в java
На C++ размещение файлов в интегрированных средах (не консольное приложение):
1. Record.h – заголовочный файл базового класса
class Record
{
public:
void Init (int m,int s);
int Numbersec();
protected: // вместо private:
int min;
int sec;
};
2. Record.cpp – файл с методами базового класса
int Record::Numbersec()
{
return min*60+sec;
}
void Record::Init(int m,int s)
{
min=m;
sec=s;
}
3. Sprint.h - Заголовочный файл производного класса
class Sprint : public Record // Sprint-наследник Record
{
public:
// новые методы Sprint
void Putdec(int d);
int Numberdec();
private:
// новое поле Sprint
int dec;
};
4. Sprint.cpp – файл с методами производного класса
void Sprint::Putdec(int d)
{
dec=d;
}
int Sprint::Numberdec()
{
int k;
k=Numbersec();
return k*10+dec;
}
5. lab4.cpp – основной файл с функцией main
int main(int argc, char* argv[])
{
int m,n;
Record x,y;
Sprint z;
.......
}
Пакет на java позволяет разнести классы по отдельным файлам и обеспечить связь между полями и методами различных классов. Пакет – отдельный каталог, в котором размещается несколько файлов – public классов.
Пример создания пакета
Создание проекта: file – new – java project (lab4)
Создание пакета: file – new – Package (sports)
Создание отдельных 3 файлов-public классов
file - new – class
package sports;
public class Record
{
protected int min,sec;
public void Init(int m,int s)
{
min=m;
sec=s;
}
public int Numbersec()
{
return min*60+sec;
}
}
file - new – class
package sports;
public class Sprint extends Record
{
private int dec;
public void Putdec(int d)
{
dec=d;
}
public int Numberdec()
{
int k;
k=min*60+sec;
return k*10+dec;
}
}
file - new – class
package sports;
public class worksport
{
public static void main (String args[] )
{
int p;
Record a=new Record();
a.Init(2, 40);
p=a.Numbersec();
System.out.printf("%d\n ", p);
Sprint b=new Sprint();
b.Init(1, 10);
b.Putdec(6);
p=b.Numberdec();
System.out.printf("%d\n ", p);
}
}
Размещение:
lab4\\src\\sports\\
record.java sprint.java worksport.java
6) Перегрузка методов и явное указание класса вызываемого метода
Возможна перегрузка метода из базового класса в производном классе.
Пример – переопределение Init в Sprint
class Record
{
public:
void Init (int m,int s);
protected:
int min;
int sec;
};
void Record::Init(int m,int s)
{
min=m;
sec=s;
}
class Sprint : public Record
{
public: