Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
ООП на языке С++.docx
Скачиваний:
0
Добавлен:
01.05.2025
Размер:
2 Мб
Скачать
☆

2.10. Упражнения

Упражнение 1. В этом упражнении мы покажем, что функции-члены базового и производного классов не составляют множество перегруженных функций, т.е. функция set класса CDerived скрывает видимость функции-члена CBase::set, а не перегружает ее. Вызов функции-члена базового класса из производного в этом случае приводит к ошибке при компиляции.

В среде Microsoft Visual C++ создайте следующую программу и попытайтесь ее откомпилировать.

#include<iostream.h>

class CBase

{

protected:

int x;

public:

CBase(int);

void print();

void set(int);

};

CBase::CBase(int X):x(X){}

void CBase::print(){cout<<x<<endl;}

void CBase::set(int X){x=X;}

class CDerived:public CBase

{

protected:

int y;

public:

CDerived(int,int);

void print();

void set(int,int);

};

CDerived::CDerived(int X,int Y):CBase(X),y(Y){}

void CDerived::print(){cout<<x<<' '<<y<<endl;}

void CDerived::set(int X,int Y){x=X;y=Y;}

int main()

{

CDerived ob(5,6);

ob.set(7,8);

ob.print();

ob.set(9);// Ошибка компиляции

ob.print();

ob.CBase::print();

return 0;

}

При компиляции выделенной строки вы получите сообщение:

Compiling...

error C2660: 'set' : function does not take 1 parameters

Error executing cl.exe.

Замените ошибочную строку строкой b.set(9);

на ob.CBase::set(9); откомпилируйте и выполните программу, и вы увидите, что она выполняется без ошибки.

Результат выполнения посмотрите здесь inh1.exe

Другой способ решения этой проблемы–написать в производном классе небольшую встроенную функцию заглушку для вызова функции базового класса.

class CDerived:public CBase

{

protected:

int y;

public:

CDerived(int,int);

void print();

void set(int,int);

void bset(int i){CBase::set(i);} //Функция-заглушка

};

Выполнив

int main()

{

CDerived ob(5,6);

ob.set(7,8);

ob.print();

ob.bset(9); //

ob.print();

ob.CBase::print();

system("pause");

return 0;

}

Вызов ob.bset(9); дает тот же результат, что и ob.CBase::set(9);

Упражнение 2. В этом упражнении мы покажем использование виртуальных функций.

Создадим иерархию классов: «птицы» имеют свойство «летать» и наследуемый класс «пингвин», который летать не умеет.

#include<iostream.h>

//птицы

class bird{

//...

public:

void fly()const{cout<<"fly"<<endl;} //может летать

//Если не const, то при вызове в функции alarm() b.fly();

// сообщение

//cannot convert 'this' pointer from 'const class bird' to 'class bird &'

};

//пингвин

class penguin:public bird{

//...

public:

// Переопределяем, чтобы пингвин не летал

void fly()const{cout<<"nofly"<<endl;}

};

int main()

{

bird b;

penguin p;

b.fly();//летит

p.fly();//не летит

return 0;

}

Создадим и выполним эту программу. Все нормально: птицы летают, но пингвин не летает.

Усложним задание. Добавим функцию alarm() – сигнал «тревога», который поступает всем птицам, в том числе и пингвину. Реакция птиц на сигнал «тревога» : убежать, улететь.

#include<iostream.h>

//птицы

class bird{

//...

public:

void fly()const{cout<<"fly"<<endl; }

};

//пингвин

class penguin:public bird{

//...

public:

void fly()const{cout<<"nofly"<<endl;}

};

//Сигнал тревоги

void alarm(const bird& b)

{

b.fly();

}

int main()

{

bird b;

penguin p;

b.fly();//летит

p.fly();//не летит

alarm(b);//полетела

alarm(p);//как ни странно, и пингвин полетел

return 0;

}

Создадим и выполним эту программу. Видим, что все птицы, в том числе и пингвин, летят.

Сделаем функцию fly() виртуальной.

virtual void fly()const{cout<<"fly"<<endl;

Создадим и выполним эту программу. Все нормально: птицы летают, но пингвин не летает.

int main()

{

bird b;

penguin p;

b.fly();//летит

p.fly();//не летит

alarm(b);//полетела

alarm(p);//не летит, а только бежит

return 0;

}

Более грамотным решением будет создание абстрактного класса «птицы» с абстрактной виртуальной функцией fly(). В конкретном классе птиц эта функция переопределяется должным образом.

#include<iostream.h>

// Абстрактный класс-птицы

class bird{

//...

public:

virtual void fly()const=0;//Абстрактный метод-

//должен быть переопределен в производных классах

};

//ворона

class crow:public bird{

//...

public:

//Ворона летает

void fly()const{cout<<"fly"<<endl;}

};

//пингвин

class penguin:public bird{

//...

public:

//Пингвин не летает

void fly()const{cout<<"nofly"<<endl;}

};

//Сигнал тревоги

void alarm(const bird& b)

{

b.fly();

}

int main()

{

crow c;

penguin p;

c.fly(); // летит

p.fly(); //не летит

alarm(c); //полетела

alarm(p); //не летит, а бежит

return 0;

}