Студопедия
Случайная страница | ТОМ-1 | ТОМ-2 | ТОМ-3
АрхитектураБиологияГеографияДругоеИностранные языки
ИнформатикаИсторияКультураЛитератураМатематика
МедицинаМеханикаОбразованиеОхрана трудаПедагогика
ПолитикаПравоПрограммированиеПсихологияРелигия
СоциологияСпортСтроительствоФизикаФилософия
ФинансыХимияЭкологияЭкономикаЭлектроника

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

Наследование классов | Применение наследования | Использование объектов производного класса в качестве объектов базового класса | Dynamic_cast <тип *> (выражение). | Плата за полиморфизм | Абстрактные базовые классы и чисто виртуальные функции | Множественное наследование |


Читайте также:
  1. Конспект урока в 4 классе.
  2. Конструкторы и деструкторы
  3. Конструкторы и деструкторы
  4. Обращаем внимание на особенности организации образовательного процесса в Х классе.
  5. Оператор присваивания
  6. Перегрузка арифметических операций

 

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

 

При создании объекта производного класса вызывается конструктор базового класса, чтобы сначала “сконструировать” базовую часть класса. Конструктор базового класса, обычно, вызывается как часть списка инициализаторов в определении конструктора производного класса. Это вполне естественно – для завершения создания объекта сначала нужно создать объект базового класса. Затем конструктор производного класса “переключает свое внимание” на свои собственные данные-члены. Если какие-то параметры требуются конструктору базового класса, то они должны быть предоставлены в виде списка параметров конструктора производного класса (а в конструкторе базового, после двоеточия, они выступают в роли фактических параметров, см. пример выше: Leaf1(int a, int b, int c): Derived1(a, b, c) { }. Таким образом, в списке инициализации мы, по сути, осуществляем вызов конструктора базового класса). Если никаких параметров для конструктора базового объекта в конструкторе производного класса не указывается, то для базового класса вызывается конструктор по умолчанию. Но если в базовом классе присутствуют только конструкторы, которые требуют некоторых параметров, то производный класс должен иметь конструктор, имеющий в списке эти параметры, даже если сам производный класс не нуждается в (явном) конструкторе.

 

Поскольку деструктор не нуждается в каких-либо параметрах, то деструктор базового класса вызывается автоматически деструктором производного класса после завершения его части работы. В целом же, необходимость деструктора в производном классе возникает тогда, когда нужно освобождать какие-либо ресурсы, выделенные конструктором при создании объекта. Если явного деструктора в классе нет, то компилятор обеспечивает свой деструктор по умолчанию, в котором вызывается и деструктор базового класса. При уничтожении объекта деструкторы вызываются в обратном, по отношению к вызовам конструкторов, порядке. В следующем примере обратите внимание на то, как определены конструкторы (особенно, конструктор копирования), деструктор, функции, перегружающие операции присваивания и операцию вывода.

 

Пример 14-6.

 

#include <iostream.h>

#include <string.h>

 

class Base

{

protected:

int id;

char * name;

public:

// конструктор по умолчанию

Base(int a = 0, char * s = ""): id(a)

{

if (!s) { name = NULL; }

else

{

name = new char[strlen(s) + 1];

strcpy(name, s);

}

cout << "base default constructor\n";

}

// конструктор копирования

Base(const Base& b): id(b.id)

{

if (!b.name) { name = NULL; }

else

{

name = new char[strlen(b.name) + 1];

strcpy(name, b.name);

}

cout << "base copy constructor\n";

}

// деструктор

~Base()

{

delete [ ] name;

cout << "base destructor\n";

}

const Base& operator= (const Base& b);

friend ostream& operator << (ostream&, const Base&);

};

 

const Base& Base::operator= (const Base& b)

{

id = b.id;

if (this!= &b) // Проверяем случай присваивания объекта самому себе.

{

delete [ ] name; // Разрушаем старый объект.

if (!b.name) { name = NULL; }

else

{

name = new char[strlen(b.name) + 1];

strcpy(name, b.name);

}

}

cout << "base assignment operator\n";

return *this;

}

 

ostream& operator << (ostream& out, const Base& b)

{

out << "Base member id = " << b.id << endl;

out << "Base member name = " << b.name << endl;

 

return out;

}

 

class Derived: public Base

{

float f;

char * label;

public:

// конструктор по умолчанию

Derived(int a = 0, char * s = "", float x = 0, char * t = ""): Base(a, s), f(x)

{

if (!t) { label = NULL; }

else

{

label = new char [strlen(t) + 1];

strcpy(label, t);

}

cout << "derived default constructor\n";

}

// конструктор копирования

Derived(const Derived& d): Base(d), f(d.f)

// d используется как экземпляр класса Base

{

if (!d.label) { label = NULL; }

else

{

label = new char [strlen(d.label) + 1];

strcpy(label, d.label);

}

cout << "derived copy constructor\n";

}

// деструктор

~Derived()

{

delete [ ] label;

cout << "derived destructor\n";

}

const Derived& operator= (const Derived& d);

friend ostream& operator << (ostream&, const Derived&);

};

 

const Derived& Derived::operator= (const Derived& d)

{

if (this!= &d)

{

delete [ ] label;

Base::operator=(d); // Присваиваем базовую часть d (т.е., объект класса Base)

// базовой части объекта, который вызвал этот оператор;

f = d.f;

if (!d.label) { label = NULL; }

else

{

label = new char [strlen(d.label) + 1];

strcpy(label, d.label);

}

cout << "derived assignment operator\n";

}

return *this;

}

 

ostream& operator << (ostream& out, const Derived& d)

{

out << (Base)d; // Превращаем d в объект класса Base для вывода членов класса Base.

out << "Derived member f = " << d.f << endl;

out << "Derived member label = " << d.label << endl;

return out;

}

 

int main()

{

Derived d1, d2(d1);

 

return 0;

}

 

Программа выводит:

 

base default constructor // конструктор базовой части объекта d1

derived default constructor // конструктор дополнительной части d1

base copy constructor // копирование базовой части d1 в базовую часть объекта d2

derived copy constructor // копирование оставшейся части d1 в d2

derived destructor // вызван деструктор производного класса для разрушения d2

base destructor // вызван деструктор базового для разруш-ия базовой части d2

derived destructor // деструктор производного для разрушения d1

base destructor // деструктор базового для разрушения базовой части d1

 

 


Дата добавления: 2015-11-16; просмотров: 81 | Нарушение авторских прав


<== предыдущая страница | следующая страница ==>
Информация о типе во время выполнения (RTTI) (лучше почитать после обсуждения виртуальных функций).| Виртуальные функции

mybiblioteka.su - 2015-2024 год. (0.015 сек.)