Некоторые особенности конструкторов

Содержание

Слайд 2

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

Отличие конструктора копирования от конструктора преобразования

Входной параметр конструктора копирования имеет тип,

описываемый данным классом.
Если описывается класс Х, то его конструктор копирования может иметь один из следующих прототипов:
Х(Х&);
Х(const Х&);
Слайд 3

Следующие инструкции вызовут конструктор копирования класса MyClass: MyClass x = y;

Следующие инструкции вызовут конструктор копирования класса MyClass:
MyClass x = y; //

y явно инициализирует x
func1(y); // y передается в качестве параметра (по значению)
y = func2(); // y получает возвращаемый объект.
Слайд 4

В двух первых случаях конструктору копирования передается ссылка на y. В

В двух первых случаях конструктору копирования передается ссылка на y. В

последнем случае конструктору копирования передается ссылка на объект, возвращаемый функцией func2().
Слайд 5

Запрет копирования объектов Возможны ситуации, когда операция копирования объекта не имеет

Запрет копирования объектов

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

и должна быть запрещена
Объект должен существовать в единственном экземпляре внутри приложения, например, «клавиатура»
Для запрещения копирования объекта, конструктор копирования объявляется в закрытой (private) области класса
Реализацию данного конструктора можно не писать
Слайд 6

Пример class CFile { public: // … private: CFile(Cfile const&); // … };

Пример

class CFile
{
public:
// …
private:
CFile(Cfile const&);
// …
};

Слайд 7

Наследование, множественное наследование

Наследование, множественное наследование

Слайд 8

Наследование Объект производного класса обладает всеми методами и атрибутами базового. Помимо

Наследование

Объект производного класса обладает всеми методами и атрибутами базового. Помимо них,

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

Наследование. Пример class A { int m_i; float m_f; }; class

Наследование. Пример

class A
{
int m_i;
float m_f;
};
class B: A
{
double m_d;
};
class

C: B
{
long m_l;
};
Слайд 10

Наследование. Пример class A { int m_i; float m_f; MethodA(); };

Наследование. Пример

class A
{
int m_i;
float m_f;
MethodA();
};
class B: A
{
double

m_d;
};
class C: B
{
long m_l;
};

B b;
b.MethodA();

Слайд 11

Множественное наследование class A { int m_i; }; class B {

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

class A
{
int m_i;
};
class B
{
double m_d;
};
class C: A,

B
{
float m_f;
};
Слайд 12

Модификаторы доступа public Поле/метод с таким модификатором доступно отовсюду (из самого

Модификаторы доступа

public Поле/метод с таким модификатором доступно отовсюду (из самого класса, из

его потомков, из глобальных функций).
protected Доступно из самого класса и производных от него, но недоступно извне.
private Доступно только из самого класса.
Слайд 13

Модификаторы доступа При наследовании также указывается модификатор доступа. В соответствии с

Модификаторы доступа

При наследовании также указывается модификатор доступа. В соответствии с ним

в производном классе изменяются уровни доступа.
Для класса можно указать дружественные классы и функции (friend). Они будут иметь доступ ко всем полям класса.
Слайд 14

Модификаторы доступа. Пример. class A { private: int m_priv; protected: int

Модификаторы доступа. Пример.

class A
{
private:
int m_priv;
protected:
int m_prot;
public:
int

m_pub;
};
class B: public A;
class C: protected A;
class D: private A;

m_priv доступен только из класса A;
m_prot доступен из классов A и производных от него (в B,C это поле остается protected, в D становится private);
m_pub доступен из классов A, в производных от него, а также извне. В классе B это поле остается public, в классе C становится protected, в классе D – private.

Слайд 15

Полиморфизм

Полиморфизм

Слайд 16

Статический полиморфизм в С++ определение в одном классе нескольких методов с

Статический полиморфизм в С++

определение в одном классе нескольких методов с одним

и тем же именем, но разными типами и количеством аргументов
// определение класса комплексных чисел:
class Complex
{
public:
int real; // вещественная часть
int imaginary; // мнимая часть
// прибавить комплексное число:
Complex operator+(const Complex x) const;
// прибавить целое число:
Complex operator+(long x) const;
};

void main ()
{
Complex c1,c2;
long x;
c1 + c2;
c2 + x;
}

Слайд 17

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

Виртуальные функции

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

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

Виртуальные функции. Пример. class Shape { int cx, cy; virtual void

Виртуальные функции. Пример.

class Shape
{
int cx, cy;
virtual void print();
};
class

Circle: Shape
{
int r;
virtual void print();
};
class Rect: Shape
{
int w,h;
virtual void print();
};

Пусть есть массив Shape* shapes[];
Несмотря на то, что тип элементов массива – Shape*, т.е. указатель на объект типа Shape, реально по указателю может лежать любой объект производного типа.
Если мы напишем такой цикл, то вызываться будет функция print того типа, который на самом деле находится по адресу shapes[i]:
for(int i = 0; i < N; i++) {
shapes[i]->print();
}

Слайд 19

Дружественные функции и классы

Дружественные функции и классы

Слайд 20

Дружественные функции и классы Иногда желательно дать функциям, не являющимися элементами,

Дружественные функции и классы

Иногда желательно дать функциям, не являющимися элементами, доступ

к личной части объекта класса.
Для этого в декларации класса помещается декларация функции, перед которой стоит ключевое слово friend.
Особенности дружественных функций:
дружественная функция может быть другом двух и более классов;
декларация friend - это только декларация, вводящая имя функции в самую широкую область действия в программе; декларацию можно поместить как в private-, так и в public- части описания класса – компилятору это безразлично;
дружественная функция лишь имеет права доступа к приватной части объекта: если она не является полноправной функцией-элементом, то у нее нет и указателя this.
Иными словами, встретив ключевое слово friend, компилятор просто отключает проверку прав доступа.
Замечание: друзья не наследуются
Слайд 21

©Павловская Т.А. (СПбГУ ИТМО) class monstr { int health, ammo; char

©Павловская Т.А. (СПбГУ ИТМО)

class monstr
{
int health, ammo;
char *name;
public:
friend int steal_ammo(monstr

&);
friend void hero::kill(monstr &);
int get_health(){return health;}
int get_ammo(){return ammo;}
};
class hero {
public:
void kill(monstr &);
};

Дружественные функции.Пример

Слайд 22

©Павловская Т.А. (СПбГУ ИТМО) Дружественные функции и классы Дружественная функция объявляется

©Павловская Т.А. (СПбГУ ИТМО)

Дружественные функции и классы

Дружественная функция объявляется внутри класса,

к элементам которого ей нужен доступ, с ключевым словом friend.
Дружественная функция может быть обычной функцией или методом другого ранее определенного класса.
Слайд 23

©Павловская Т.А. (СПбГУ ИТМО) Дружественные функции.Пример int steal_ammo(monstr &M) { return

©Павловская Т.А. (СПбГУ ИТМО)


Дружественные функции.Пример

int steal_ammo(monstr &M)
{
return --M.ammo;
}
void hero::kill(monstr &M)
{
M.health

= 0; M.ammo = 0;
}
Слайд 24

©Павловская Т.А. (СПбГУ ИТМО) class hero{ ... friend class patriarch; }

©Павловская Т.А. (СПбГУ ИТМО)

class hero{
...
friend class patriarch;
}
class patriarch
{
...
void f1();
void f2();
}

Дружественные

классы - пример