Сдам Сам

ПОЛЕЗНОЕ


КАТЕГОРИИ







Перегруженные функции при динамическом связывании





Общее правило перегрузки функций: перегруженная (переопределенная) функция базового класса в производных классах прячет все другие версии этой функции в базовом классе.

//f1.h

#include <iostream.h>

class Base

{public:

virtual int f() {cout<<"Base::f()"<<endl;return 1;}

virtual void f(char *s) {cout<<s<<endl;}

virtual void g() {};

};

class Derived1: public Base

{public:

void g() {cout<<"Derived1::g()"<<endl;}

};

class Derived2: public Base

{public:

int f() {cout<<"Derived2::f()"<<endl;return 2;}

};

/*class Derived3: public Base

{public:

void f() {cout<<"Derived3::f()"<<endl;} //Ошибка, так как компилятор не позволяет изменять тип возвращаемого значения для перегруженной виртуальной функции

};*/

//f1.cpp

#include "f1.h"

void main()

{ char *s;

s="Hello!";

Derived1 d1;

int x=d1.f(); //Base::f()

d1.f(s); //"Helo!"

Derived2 d2;

x=d2.f(); //Direved2:f()

//d2.f(s); //ошибка! функция f не имеет ни одного параметра

Base* b2=&d2;

b2->f();//Direved2:f()

b2->f(s);//Hello!

}

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

Множественное наследование описывает родство между классами, при котором один класс может иметь несколько базовых.

class A {…};

class B {…};

class C {…};

class D: public A, public B, public C {…};

Вызов конструкторов происходит в том порядке, в котором были объявлены базовые классы:

A::A()

B::B()

C::C()

D::D()

//f1.h

Class A

{public:

void Display(void) {…}

};

Class B

{public:

void Display(void) {…}

};

 

class C: public A, public B

{public:

void f(void);

};

Если имеем реализацию:

void C::f(void)

{Display();}

то компилятор не будет знать, какую функцию Display() вызывать. Нужно указывать явно.

void C::f(void)

{ A::Display();

B::Display();

}

Конструктор класса, у которого несколько родителей, перед вызовом своего конструктора вызывает все конструкторы базовых классов в порядке их объявления. Их можно вызвать явно:

Class C: public A, public B

{public:

C():A(), B() {};

void f(void);

};

Если через объект класса C попытаться обратиться к методам класса W, то компилятор выдаст ошибку. Выходом из этой проблемы будет использование виртуального базового класса

//f1.h

#include <iostream.h>

class W

{public:

virtual void f() {cout<<"W::f()"<<endl;}

virtual void g() {cout<<"W::g()"<<endl;}

virtual void h() {cout<<"W::h()"<<endl;}

};

class A:public virtual W

{public:

void g() {cout<<"A::g()"<<endl;}

};

class B:public virtual W

{public:

void f() {cout<<"B::F()"<<endl;}

};

class C: public A, public B

{public:

void f() {cout<<"C::f()"<<endl;}

};

//f1.cpp

#include "f1.h"

void main()

{ C* pc = new C;

pc->f(); //C::f()

pc->g(); //A::g()

pc->h(); //W::h()

((A*)pc)->f(); //C::f(). pc – указатель на C, насильственно преобразуем его к указателю на A; в описании класса A функции f нет, она описана в базовом классе W, но как виртуальная; далее происходит анализ класса, на который указывает pc, то есть класса C, в нем обнаруживается реализация функции f(), вызов которой и происходит. Если слово virtual перед f() в W убрать, тогда будет вызвана f из W.

((W*)pc)->f(); //C::f()

B* pb = new B;

pb->f(); //B::f()

pb->g(); //W::g();

pb->h(); //W::h()

((W*) pb)->f(); //B:f()

A* pa = new A;

pa->f(); //W::f()

pa->g(); //A::g()

pa->h(); //W::h()

((W*) pa)->g(); //A::g()

}

Для описания иерархий множественного наследования используется прямой ациклический граф. Виртуальные базовые классы инициализируются перед любыми невиртуальными базовыми классами в том порядке, в котором они появляются в прямом ациклическом графе наследования при просмотре его снизу вверх и слева направо. Для приведенного выше примера порядок вызова конструкторов следующий: W(), A(), B(), C().

class A {};

class B: public virtual A {};

class C: public virtual A {};

class D: public A {};

class E: public B, public C, public D {};

Дерево наследования приведенной выше иерархии изображено на рисунке ниже.

Порядок вызова конструкторов для класса E таков: A(), B(), C(), D(), E().

 

Ключ доступа Спецификатор базового доступа Доступ в производном классе Комментарий
private private protected public private private private все private
protected private protected public private protected protected все protected, кроме private
public private protected public private protected public не изменяется

 


ЧТО НЕОБХОДИМО ЗНАТЬ

1. Наследование представляет собой способность производить новый класс из существующего базового класса.

2. Когда вы порождаете один класс из другого (базового класса), производный класс наследует элементы базового класса.

3. Для порождения класса из базового начинайте определение производного класса ключевым словом class, за которым следует имя класса, двоеточие и имя базового класса, например class dalmatian: dog.

4. Когда вы порождаете класс из базового класса, производный класс может обращаться к общим элементам базового класса, как будто эти элементы определены внутри самого производного класса. Для доступа к частным данным базового класса производный класс должен использовать интерфейсные функции базового класса.

5. Внутри конструктора производного класса ваша программа может вызвать конструктор базового класса, указывая двоеточие, имя конструктора базового класса и соответствующие параметры сразу же после заголовка конструктора производного класса.

6. Чтобы обеспечить производным классам прямой доступ к определенным элементам базового класса, в то же время защищая эти элементы от оставшейся части программы, C++ обеспечивает защищенные (protected) элементы класса. Производный класс может обращаться к защищенным элементам базового класса, как будто они являются общими. Однако для оставшейся части программы защищенные элементы эквивалентны частным.

7. Если в производном и базовом классе есть элементы с одинаковым именем, то внутри функций производного класса C++ будет использовать элементы производного класса. Если функциям производного класса необходимо обратиться к элементу базового класса, вы должны использовать оператор глобального разрешения, например base class:: member.

8. Полиморфный объект может изменять форму во время выполнения программы. Вы создаете полиморфные объекты, используя классы, порожденные от существующего базового класса.

9. В базовом для полиморфного объекта классе вы должны определить одну или несколько функций как виртуальные (virtual).

10. В общем случае полиморфные объекты отличаются использованием виртуальных функций базового класса.

11. Для создания полиморфного объекта вам необходимо создать указатель на объект базового класса.

12. Для изменения формы полиморфного объекта вы просто направляете указатель на различные объекты, присваивая новый адрес объекта указателю на полиморфный объект.

13. Чисто виртуальная функция — это виртуальная функция базового класса, для которой в базовом классе не определены операторы. Вместо них базовый класс присваивает такой функции значение 0.

14. Производные классы должны обеспечить определение функции для каждой чисто виртуальной функции базового класса.

15. Множественное наследование является способностью порожденного класса наследовать характеристики нескольких базовых классов.

16. Для порождения класса из нескольких базовых после имени нового класса и двоеточия вы указываете имена базовых классов, разделяя их запятыми, например class cabbit: public cat, public rabbit.

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


Задания

  1. Разработать систему классов студент, преподаватель, персона, заведующий кафедрой. Персона характеризуется датой рождения, именем, фамилией, контактными данными. Студент имеет студенческий билет и зачетную книжку, в которой хранится информация об оценках и предметах. Преподаватель характеризуется кафедрой и предметами, которые ведет у групп студентов. Заведующий кафедрой также характеризуется кафедрой, предметами, которые ведет у групп студентов.

2. Разработать программу с использованием наследования классов, реализующую классы: железнодорожный вагон; вагон для перевозки автомобилей; цистерна. Используя виртуальные функции, не зная с объектом какого класса работаете, выведите на экран его вес и количество единиц товара в вагоне.

3. Разработать программу с использованием наследования классов, реализующую классы: работник больницы; медсестра; хирург. Используя виртуальные функции, не зная с объектом какого класса вы работаете, выведите на экран возраст и название должности.

4. Построить систему классов для описания плоских геометрических фигур: круга, квадрата, прямоугольника. Предусмотреть методы для создания объектов, перемещения на плоскости, изменения размеров и вращения на заданный угол. Написать программу, демонстрирующую работу с этими классами. Программа должна содержать меню, позволяющее осуществить проверку всех методов классов.

5. Создать базовый класс «треугольник», описав в нём функции задания параметров треугольника, вывода их на экран, нахождения периметра и площади. Породить от него класс «прямоугольный треугольник», переопределив функции задания параметров и нахождения площади. Треугольник задается длинами сторон. При вводе параметров обязательно обеспечить проверку на существование треугольника. При задании параметров для объекта класса «прямоугольный треугольник» проверить, действительно ли задан прямоугольный треугольник.

6. Создать базовый класс «многоугольник», описав в нём функции задания количества и длин сторон, вывода параметров многоугольника на экран, нахождения периметра. Породить от него класс «правильный многоугольник» с числом вершин 3<=N<=6, переопределив в нём функции задания количества и длин сторон и нахождения периметра.

7. Создать базовый класс «прямоугольник», определив в нем функции ввода параметров прямоугольника, вывода их на экран и нахождения площади. Породить от него класс «квадрат», переопределив функции ввода параметров и нахождения площади.

Для предложенных тем выбрать 2-3 поля данных и 2-3 виртуальных метода для отображения и изменения значений полей:







ЧТО ПРОИСХОДИТ, КОГДА МЫ ССОРИМСЯ Не понимая различий, существующих между мужчинами и женщинами, очень легко довести дело до ссоры...

ЧТО И КАК ПИСАЛИ О МОДЕ В ЖУРНАЛАХ НАЧАЛА XX ВЕКА Первый номер журнала «Аполлон» за 1909 г. начинался, по сути, с программного заявления редакции журнала...

Что способствует осуществлению желаний? Стопроцентная, непоколебимая уверенность в своем...

ЧТО ТАКОЕ УВЕРЕННОЕ ПОВЕДЕНИЕ В МЕЖЛИЧНОСТНЫХ ОТНОШЕНИЯХ? Исторически существует три основных модели различий, существующих между...





Не нашли то, что искали? Воспользуйтесь поиском гугл на сайте:


©2015- 2024 zdamsam.ru Размещенные материалы защищены законодательством РФ.