Разделы презентаций


Наследование одиночное презентация, доклад

Содержание

Определение наследованияАтрибут наследования определяется тремя известными ключевыми словами: private, public и protected, которые использовались для доступа к внутренним компонентам класса.Данный атрибут при наследовании определяет видимость компонент базового класса внутри производного. Как

Слайды и текст этой презентации

Слайд 1ООП : наследование
Наследование: это механизм, который позволяет определить новые классы

в терминах существующих классов.
При разговоре о наследовании всегда выделяют класс,

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


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

Слайд 2Определение наследования
Атрибут наследования определяется тремя известными ключевыми словами: private, public

и protected, которые использовались для доступа к внутренним компонентам класса.
Данный

атрибут при наследовании определяет видимость компонент базового класса внутри производного. Как атрибут влияет на видимость компонент базового класса?

Как можно определить наследование одного класса другим в С++?

сlass имя_производного_класса : атрибут_наследования имя_базового_класса { … };

Атрибут наследования

public

private

Производный класс

public

protected

недоступен

Производный класс

private

private

недоступен

Базовый класс

public

protected

private

protected эквивалентен private за одним исключением – все компоненты базового класса с атрибутом доступа protected доступны в производных классах.

Определение наследованияАтрибут наследования определяется тремя известными ключевыми словами: private, public и protected, которые использовались для доступа к

Слайд 3Конструкторы и деструкторы при наследовании
Правило вызова конструкторов и деструкторов при

одиночном наследовании.
При создании экземпляра производного класса сначала выполняется конструктор базового,

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

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

конструктор_производного_класса (аргументы) : конструктор_базового_класса (аргументы)

Конструкторы и деструкторы при наследованииПравило вызова конструкторов и деструкторов при одиночном наследовании.При создании экземпляра производного класса сначала

Слайд 4 Количество и тип аргументов для конструкторов производных и базового классов

могут не совпадать.
Наследование - пример
#include "iostream"
using namespace std;

class A
{
protected:

int n;
public:
A(int n=0){ this->n =n; cout << "Con A" < ~A(){ cout << "Des A" <};

class B : protected A
{
public:
void print(){cout << "n = " < B() :A(5) { cout << "Con B" < ~B(){ cout << "Des B" <};


void f() {
B obj; obj.print();
}
void main()
{ f();
char s; cin>>s;
}


Результат выполнения программы:


Слайд 5 Если конструктор базового класса имеет аргументы, то для передачи этих

аргументов их должен содержать конструктор производного класса.
Наследование – пример 2
#include

"iostream"
using namespace std;
class A
{
int n;
public:
A(int n) { this->n =n;
cout << "Con A\nn = " < }
~A(){ cout << "Des A" <};
class B : public A
{
int m;
public:
B(int m, int n) : A(n) { this->m = m;
cout << "Con B\nm = " < ~B(){ cout << "Des B" < }
};

void f()
{
B obj(1,2);
}

void main()
{ f();
char s; cin>>s;
}


Результат выполнения программы:

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


Слайд 6 Если в программе определен указатель на базовый класс, то его

можно использовать для доступа к компонентам объектов базового класса, а

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

Наследование – использование указателей

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

Слайд 7Наследование – пример 3
#include "iostream“
using namespace std;
class A
{
int n;

public:
A(int

n){ this->n =n;
cout << "Constructor A\n n = " << n << endl;
}
~A(){ cout << "Destructor A" < void print_A() { cout << "n = " << n <};

class B : public A
{
int m;
public:
B(int m, int n) :A(n) { this->m = m;
cout << "Constructor B\n m = " << m << endl;
}
~B(){ cout << "Destructor B" < void print_B() { cout << "m = " << m <};


Результат выполнения программы:


void f()
{
A obj1(5);
B obj2(1,2);
A* ptr = &obj1; ptr->print_A();
ptr = &obj2; ptr->print_A();
B* ptr2 = &obj2; ptr2->print_A();
ptr2->print_B();
}

void main()
{ f(); char s; cin>>s; }


Слайд 8
Наследование – пример 4
#include "stdafx.h"
#include
#include

class CShape {
public:
CShape();
//-------------Attributes


private:
int x,y;
public:
//------------- Implementation
int GetCoordX();
int GetCoordY();
void SetCoord(int

x, int y);
~CShape();
};
CShape::CShape(){x = y = 0;}
CShape::~CShape() { }

int CShape::GetCoordX() { return x; }
int CShape::GetCoordY() { return y; }

void CShape::SetCoord(int xS, int yS)
{ x = xS; y = yS;}




void main()
{
CShape sh;
sh.SetCoord(10,12);
std::cout<< sh.GetCoordX() << " - " <<
sh.GetCoordY() << std::endl;

char s; std::cin>>s;
}


Наследование – пример 4#include

Слайд 9Наследование (продолжение примера 4)
class CCircle: public CShape {
public:
CCircle();

//Attributes


private:
int R;

public:
// Implementation
int GetRad();
void SetRad(int

r);
int GetLengthToCenter();
~CCircle();
};

CCircle::CCircle( ) {R = 0;}
CCircle::~CCircle() { }
int CCircle::GetRad( ) { return R; }
void CCircle::SetRad(int r) { R = r; }
int CCircle::GetLengthToCenter()
{
return static_cast
(sqrt(2.0*(R+GetCoordX())*
(R+GetCoordY())));
}

CCircle cir;
cir.SetCoord(3,3);
cir.SetRad(4);
std::cout<< cir.GetRad() << " - "
<< cir.GetLengthToCenter() << std::endl;


Наследование (продолжение примера 4)class CCircle: public CShape {public: CCircle(); //Attributes private: int R; public: // Implementation int

Слайд 10
Виртуальные функции – обоснование необходимости применения
#include
using namespace std;

class A

{
int n;
public:
A(int n){this->n = n;}
void print(){cout

Base n=" << n << endl; }
};

class D : public A {
char c;
public:
D(char c): A(1) { this->c = c; }
void print(){cout << " Derived c=" << c << endl; }
};

void main()
{
A obj1(1); D obj2('W');
obj1.print();
obj2.print();

char s; std::cin>>s;
}


Результат выполнения программы:

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

Виртуальные функции – обоснование необходимости применения#include using namespace std;class A {	int n;public:	A(int n){this->n = n;}  void

Слайд 11
void main()
{
A obj1(1); D obj2('W');

obj1.print();
obj2.print();


}

// Старый

вариант
void main()
{
A obj1(1); D obj2('W');
A *ptr;
ptr =

&obj1;
ptr->print();

ptr = &obj2;
ptr->print();
}
// Новый вариант


Результат выполнения программы:

Как так получилось?

Когда указатель на базовый класс указывает на экземпляр базового класса – вызывается функция print этого класса (1-я строка результата). В случае, когда он указывает на экземпляр производного класса, по идее должна вызываться функция из производного класса. Но этого не происходит! Указатель на базовый класс может быть использован только для доступа к компонентам, которые описаны в базовом классе. Для доступа к компонентам из производных классов необходимо использовать указатель на производный класс. Эта задача решается путем использования виртуальных функций (методов).

Виртуальные функции – обоснование необходимости применения -продолжение

void main(){ A obj1(1); D obj2('W');  obj1.print(); obj2.print();}// Старый вариантvoid main(){ A obj1(1); D obj2('W'); A

Слайд 12Виртуальные функции – определение
Виртуальная функция задается точно также как

и обычная, только в начале определения такой функции ставится ключевое

слово virtual.

Виртуальная функция объявляется внутри базового класса.

Виртуальная функция не может быть статической.

Если виртуальная функция переопределяется в производных классах, то она автоматически в них становится виртуальной и в этом случае нет необходимости в использовании ключевого слова virtual.

Деструкторы могут быть виртуальными, а конструкторы – нет.

Виртуальная функция может быть вызвана как обычная.

Виртуальные функции – определение Виртуальная функция задается точно также как и обычная, только в начале определения такой

Слайд 13
Виртуальные функции – применение
#include
using namespace std;

class A {
int n;
public:
A(int

n){this->n = n;}
virtual void print(){cout

n=" << n << endl; }
};

class D : public A {
char c;
public:
D(char c): A(1) { this->c = c; }
virtual void print(){cout << " Derived c=" << c << endl; }
};

void main()
{
A obj1(1); D obj2('W');
obj1.print();
obj2.print();

char s; std::cin>>s;
}


Результат выполнения программы:

Если бы в рассмотренном примере функция print была объявлена виртуальной:

Виртуальные функции – применение#include using namespace std;class A {	int n;public:	A(int n){this->n = n;}  virtual void print(){cout

Слайд 14Виртуальные функции и полиморфизм
С понятием виртуальных функций тесно связано такое

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

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

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

Если бы в рассмотренном примере функция print в классе D описана как:
int print(int a){cout << " Derived c=" << c << endl; return a;}

то результат работы программы будет
Base n =1
Base n =1
Виртуальные функции и полиморфизмС понятием виртуальных функций тесно связано такое понятие как полиморфизм. На рассмотренном примере это

Слайд 15
Виртуальные функции - пример
#include
using namespace std;

class B {
public:

virtual void f(int) { cout

virtual void f(double) { cout << " fB(dbl)\n"; }
};

class D : public B {
public:
virtual void f(int) { cout << " fD(int)\n"; }
};


void main()
{
D d;
B b, *pb = &d;
b.f(6);
d.f(6);
b.f(6.2);
d.f(6.2);
pb->f(6);
pb->f(6.2);
}


Результат выполнения программы:

Виртуальные функции - пример#include using namespace std;class B {public:  virtual void f(int) { cout

Слайд 16Виртуальные функции – пример 2
#include
using namespace std;

class A {
public:

virtual void print() { cout

D : public A {
public:
void print() { cout << " Derived B \n”; }
};

class D1 : public A {
public:
void fun() { cout << " Nothing\n”; }
};

void main()
{
A obj1;
D obj2;
D1 obj3;
A *ptr;
ptr = &obj1; ptr->print();
ptr = &obj2; ptr->print();
ptr = &obj3; ptr->print(); ptr->fun();

char s; std::cin>>s;
}


Где ошибка?

Виртуальные функции – пример 2#include using namespace std;class A {public: virtual void print() { cout

Слайд 17
Виртуальные функции – пример 2’
#include
using namespace std;

class A {
public:

virtual void print(){cout

public A {
public:
void print(){cout << " DerivedB \n”; }
};

class D1 : public A {
public:
void fun(){cout << " Nothing\n”; }
};

void main()
{
A obj1; D obj2; D1 obj3; A *ptr; D1 *p;
ptr = &obj1; ptr->print();
ptr = &obj2; ptr->print();
p = &obj3; p->print(); p->fun();

char s; std::cin>>s;
}


Результат выполнения программы:

Если виртуальная функция не определена в производном классе, однако осуществляется ее вызов, то вызовется виртуальная функция из базового класса.

Виртуальные функции – пример 2’#include using namespace std;class A {public: virtual void print(){cout

Слайд 18Чисто виртуальные функции
Часто возникают ситуации, при которых виртуальные функции, определенные

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

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

virtual возвращаемый_тип имя_функции (аргументы) =0;

Данная запись при компиляции воспринимается как отсутствие определения виртуальной функции для базового класса.
Вызов такой функции будет восприниматься как ошибка.
Если в базовом классе определен прототип чисто виртуальной функции, то она должна быть обязательно определена для всех производных классов.
Если в базовом классе определена хотя бы одна чисто виртуальная функция, то такой класс называется абстрактным базовым классом. Для такого класса нельзя создать экземпляр.
Чисто виртуальные функцииЧасто возникают ситуации, при которых виртуальные функции, определенные в базовых классах не используются, а иногда

Слайд 19Раннее и позднее связывание
Особый интерес к использованию виртуальных функций появляется

при обслуживании случайных событий. Яркий пример – ожидание ввода с

клавиатуры. В зависимости от того, каков будет ввод данных, к примеру, должны будут вызываться виртуальные функции из разных производных классов с использованием указателя на базовый.
Под процессами раннего связывания понимают те процессы, которые могут быть предопределены на этапе компиляции. Пример – при использовании вызова обычных функций. Компилятор заранее знает адрес вызываемой функции и помещает его а место вызовов этой функции.
Позднее связывание реализуется при вызовах виртуальных функций. Процессы, относящиеся к позднему связыванию, определяются только на стадии выполнения программы.
Так, например, компилятор заранее может не предугадать вызов виртуальной функции для конкретных экземпляров производных классов.
Адрес виртуальной функции вычисляется только при работе программы.
Раннее и позднее связываниеОсобый интерес к использованию виртуальных функций появляется при обслуживании случайных событий. Яркий пример –

Слайд 20Виртуальные деструкторы
Виртуальные деструкторы необходимы в случаях использования указателей на базовые

классы при выделении динамической памяти под объекты производных классов
class A

{
public:
A(char* t)
{cout << " Base A(" < virtual void print()=0;
virtual ~A() {cout <<" Base destructor\n"; }
};

class Dn : public A {
int n;
public:
Dn(int n, char *id="number") : A(id)
{this->n = n;}
void print(){cout <<" n=“<< n << endl; }
~Dn () { cout << "Dn destruction\n"; }
};

class Ds : public A {
char *str;
public:
Ds(char *str, char *id="string") : A(id)
{this->str = str;}
void print(){cout << " str=" << str << endl; }
~Ds () { cout << "Ds destruction\n"; }
};


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

Слайд 21Виртуальные деструкторы -продолжение
void f()
{
A *ptr1, *ptr2;
ptr1 = new

Dn(5);
ptr2 = new Ds("hello");
ptr1->print();
ptr2->print();
delete ptr1;
delete

ptr2;
}
void main() {
f();
char s; std::cin>>s;
}

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


Результат выполнения программы:

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


Слайд 22Ключевое слово explicit
Ключевое слово explicit запрещает автоматическое создание конвертирующего конструктора.


class A { public: A(int); } // ... A a =

5; // Автоматическое преобразование int в объект A

Можно запретить создание автоматического конвертирующего конструктора:

class A { public: explicit A(int); } // ...
A a = 5; // (1) Нельзя – преобразование запрещено! A a = A(5); // (2) Будет работать копирующий конструктор,
// который тоже создается автоматически

(1) – неявный вызов (implicit) конструктора, (2) – явный вызов (explicit)

Ключевое слово explicitКлючевое слово explicit запрещает автоматическое создание конвертирующего конструктора. class A {  public:

Слайд 23Ключевое слово explicit - пример
Запись вида «cls ii( 7 );»

является явным вызовом конструктора, а «cls dd = 7;» —

неявным. Если бы конструктор с int был в private секции, то была бы выдана ошибка. Но ключевое слово explicit скывает конструктор так незаметно, что даже предупреждения компилятор не выдаст. Если скомпилировать и запустить пример, то окажется, что во втором случает будет вызван конструктор, принимающий double. Это может оказаться довольно неожиданным поворотом событий, если не разбираться в формах вызовов конструкторов.
Если написать explicit для обоих конструкторов, то ошибки можно будет избежать — компилятор подскажет где ошибка. Поэтому explicit следует писать для всех конструкторов с одним параметром, если специально не предполагается другое поведение.

#include
 
class cls
{
public:
  explicit cls( int ) {
    std::cout << "int\n";
  }
 
   cls( double ) {
    std::cout << "double\n";
  }
};
 
void main()
{
   cls ii( 7 );
   cls dd = 7;
}

Ключевое слово explicit - примерЗапись вида «cls ii( 7 );» является явным вызовом конструктора, а «cls dd

Слайд 24Тесты …
Вопрос: Что выведет следующая программа:
#include
 
int main() {

int i = 256;
unsigned char c;
for (c =

0; c < i; c++); // 1
std::cout << (char) c; // 2
// 3
}

Варианты ответа:

возникнет ошибка компиляции на строчке 1,
// т.к. пропущено тело цикла
зависит от компилятора
символ с кодом 256
возникнет ошибка компиляции, т.к. в строчке 3
// должно быть 'return 0;'
256
ничего

Тесты …Вопрос: Что выведет следующая программа: #include  int main() { int i = 256; unsigned char c;

Слайд 25 Варианты ответа:

возникнет ошибка компиляции на строчке 1,

// т.к. пропущено тело цикла
зависит от компилятора
символ с кодом 256
возникнет ошибка компиляции, т.к. в строчке 3
// должно быть 'return 0;'
256
ничего

Тесты …

Вопрос: Что выведет следующая программа:

#include
 
int main() {
int i = 256;
unsigned char c;
for (c = 0; c < i; c++); // 1
std::cout << (char) c; // 2
// 3
}


на строчке // 1 программа войдет в бесконечный цикл, т.к. значение переменной c никогда не достигнет 256 (оно будет циклически проходить значения от 0 до 255). Поэтому на экран ничего не будет выведено.

Варианты ответа: возникнет ошибка компиляции на строчке 1,

Слайд 26Тесты …
Вопрос: есть ли ошибки в этом коде?
class A

{
int a;
public:
static int GetA() { return a; }
};

Варианты

ответа:

Да

Нет

Тесты …Вопрос: есть ли ошибки в этом коде? class A { int a;public: static int GetA() {

Слайд 27Тесты …
Вопрос: есть ли ошибки в этом коде?
class A

{
int a;
public:
static int GetA() { return a; }
};

Варианты

ответа:

Да

Нет

Пояснение: статические члены класса не имеют доступа к нестатическим членам


Тесты …Вопрос: есть ли ошибки в этом коде? class A { int a;public: static int GetA() {

Слайд 28Тесты …
Выберите правильные утверждения о конструкторе класса.
Конструктор имеет то же

имя, что и класс.
Конструктор не возвращает значения.
Имя конструктора начинается с

символа ~.
Конструктор объявляется в точности так же, как и обычный метод класса.
Конструктор может иметь любое имя.

Тесты …Выберите правильные утверждения о конструкторе класса.Конструктор имеет то же имя, что и класс.Конструктор не возвращает значения.Имя

Слайд 29Тесты …
Выберите правильные утверждения о конструкторе класса.
Конструктор имеет то же

имя, что и класс.
Конструктор не возвращает значения.
Имя конструктора начинается с

символа ~.
Конструктор объявляется в точности так же, как и обычный метод класса.
Конструктор может иметь любое имя.



Тесты …Выберите правильные утверждения о конструкторе класса.Конструктор имеет то же имя, что и класс.Конструктор не возвращает значения.Имя

Слайд 30Тест с отчетом 1
1) Скомпилируется ли следующий код:
class Clazz {

};
(да/нет)
2) Перечислите все правильные способы объявления локальной константы в блоке

кода.

(1) #const size = 5;
(2) define const size 5
(3) const int size;
(4) const int size = 5;

(перечислите номера)

3) Что будет выведено на экран в результате компиляции и выполнения следующего кода?

Варианты ответа:

(1) Ошибка компиляции
(2) 1711
(3) 2323
(4) Ошибка выполнения
(5) 2424

(укажите номер)

#include
 
int a = 23;
 
int main(int argc, char * argv[])
{
++--++--++--++--++--++--a;
++a; std::cout << a; --a;
++--++--++--++--++--++--a;
++a; std::cout << a; --a;
++--++--++--++--++--++--a;
}

Тест с отчетом 11) Скомпилируется ли следующий код:class Clazz { };(да/нет)2) Перечислите все правильные способы объявления локальной

Обратная связь

Если не удалось найти и скачать доклад-презентацию, Вы можете заказать его на нашем сайте. Мы постараемся найти нужный Вам материал и отправим по электронной почте. Не стесняйтесь обращаться к нам, если у вас возникли вопросы или пожелания:

Email: Нажмите что бы посмотреть 

Что такое TheSlide.ru?

Это сайт презентации, докладов, проектов в PowerPoint. Здесь удобно  хранить и делиться своими презентациями с другими пользователями.


Для правообладателей

Яндекс.Метрика