10. Простое наследование.
Простое наследование описывает родство между двумя классами:
один из которых наследует второму. Класс, нахо дящийся на вершине иерархии, называется базовым
классом. Прочие классы называются производными классами. Из одного класса могут
выводится многие классы, но даже в этом случае
подобный вид взаимосвязи остается простым наследованием.
Базовый класс часто называют предком, а производный класс –
потомком.
Производный класс наследует из базового
данные-члены и функции-члены, но не конструкторы и деструкторы.
class Tbase { //Базовый класс
private:
int count;
public:
TBase() {count = 0;}
void SetCount(int n) {count = n;}
int GetCount(void)
{return count;}
};
class TDerived: public TBase { //Производный класс
public:
TDerived(): Tbase() {}
void ChangeCount(int n) {SetCount(GetCount() + n);}
};
Производный класс назван TDerived.
За именем сле-дует двоеточие и одно из ключевых слов – public, protected, private. После этих элементов имя базового класса TBase. Открытые члены открытого класса остаются открытыми в
производном классе:
class TDerived:
public TBase {}
Все закрытые члены Tbase остаются
закрытыми и в Tderived нельзя получить к ним доступ.
Можно объявить базовый класс закрытым:
class TDerived:
private TBase {}
Все открытые члены в базовом классе становятся закры-тыми в TDerived.
Последующие наследования TDerived не смо-гут получить доступа в членам TBase. Обычно в производном классе есть
конструктор, если он был в базовом. Он должен вызывать конструктор
базового класса:
TDerived(): TBase()
{}
Кроме этого в нем могут выполняться и другие действия,
например:
TDerived():TBase() {cout <<" I am being initialized" <<endl;}
Можно реализовать объявленный конструктор отдельно:
TDerived::TDerived()
: TBase()
{ // операторы
}
Производный класс наследует count
из базового класса, но так как он закрыт в TBase доступ к нему возможен только через
функции-члены класса TBase. В производном классе
можно определить функцию, которая будет обращаться к наследованным функциям-членам
класса TBase:
void ChangeCount(int n) {SetCount(GetCount() +n);}
Защищенные члены класса – это нечто среднее между от-крытыми и закрытыми членами. Подобно закрытым они
доступны только функциям-членам класса. Вне класса они недоступны. Подобно открытым
они доступны функциям-членам производных классов.
- закрытые члены доступны только в том классе, в кото-ром они объявлены;
- защищенные члены доступны членам их собственного класса и
всем членам производных классов;
- открытые члены доступны членам их собственного класса,
членам производных классов и всем остальным пользователям этого класса.
Спецификаторы (public, private, protected) влияют на
статус наследуемых членов:
- члены открытого базового класса в производном классе
сохраняют свои спецификации доступа;
- открытые члены защищенного базового класса становятся
закрытыми в производном классе. Защищенные и закрытые сохраняют свои
первоначальные спецификации;
- все члены закрытого базового класса становятся закрытыми в
производном классе независимо от их перво-начальной спецификации доступа.
Если хотите сделать открытыми в производном классе только
некоторые из наследуемых членов, можно выбо-рочно
квалифицировать один или несколько из них.
class A {
public:
int x;
A() {
x=0;}
void
Display(void) { count << "x = " << x << endl;}
};
class B:
private A {
public:
A::Display; // квалифицируем как открытый член класса
B(): A() {}
};
В производном классе деструктор нужен только в том случае,
если необходимо что-то удалять.
// Программа 1
#include
<iostream.h>
#include
<string.h>
class TBase { //Базовый класс
private:
char *basep;
public:
TBase(const char *s) {basep = strdup(s); }
~TBase()
{delete basep;}
const char *GetStr(void) {
return basep; }
};
class TDerived: public TBase { //Производный класс
private:
char *uppercasep;
public:
TDerived(const char* s): TBase(s) {
uppercasep = strupr(strdup(s));}
~TDerived()
{delete uppercasep;}
const char *GetUStr(void)
{ return uppercasep;}
};
void
main()
{
TBase president("George Washington");
cout << "Original string: "
<< president.GetStr() << endl;
TDerived pres("George
Washington");
cout << "Uppercase string:"
<< pres.GetUStr() << endl;
}
В производном классе обычно добавляются новые дан-ные и функции-члены. Однако
существует возможность заме-щения
функций-членов, наследованных от базового класса. Например:
//Программа 2
#include
<iostream.h>
#include
<string.h>
class TBase { //Базовый класс
private:
char *basep;
public:
TBase(const char *s) {basep = strdup(s); }
~TBase()
{delete basep;}
void
Display(void) { cout << basep
<< endl;}
};
class TState: public TBase { //Производный класс
public:
TState(const char *s):TBase (s)
{}
void
Display(void); // замещающая функция
};
void TState::Display(void)
{
cout << "State: "; //Новый оператор
TBase::Display();
//Вызов замещенной функции
}
void
main()
{
TState object("Welcome to Borland C++5 programming!");
object.Display();
}