Загрузка...

Простое и множественное наследование


3.1. Простое наследование.

Простое наследование описывает родство между двумя классами: один из которых наследует второму. Класс, нахо дящийся на вершине иерархии, называется базовым классом. Прочие классы называются производными классами. Из одного класса могут выводится многие классы, но даже в этом случае подобный вид взаимосвязи остается простым наследованием.

Базовый класс часто называют предком, а производный класс — потомком.

Производный класс наследует из базового данные-члены и функции-члены, но не конструкторы и деструкторы.

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();

}

3.2. Множественное наследование

Построение производного класса на основе нескольких базовых выглядит очень просто: вместо имени одного базового класса (вместе с его атрибутом) используется список имен, разделенный запятыми, например:

class A { /*…*/ };

class B { /*…*/ };

class C: public A, private B { /*…*/ };

Передача аргументов конструкторам базовых классов из конструктора производного класса производится так же как и раньше:

С::С( int a, char* str) : A(a), B(str) { /*…*/ };

Загрузка...