Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
ТООП конспект весь.doc
Скачиваний:
0
Добавлен:
01.04.2025
Размер:
21.89 Mб
Скачать

Операции new/delete.

Переопределение операций.

A *pa;

pa=new A; -> obj.operator new (size_t unsigned size)

Задачей new не является вызов конструктора, он вызывается потом.

delete pa;

}

new и delete перегружаются парой. Если перегрузить new, нужно перегрузить delete.

new[]/delete[] для массивов

new[] так же получает один явный аргумент – размер всего создаваемого массива объектов.

#include <cstdlib>

using namespace std;

/*все имена стандартной библиотеки находятся в std*/

/*За счет этого имеет прямой доступ ко всем именам стандартной библиотеки C++*/

class A

{

public:

void *operator new(size_t size)

return malloc(size);

}

void operator delete (void *p)

{

free(p);

void *operator new[] (size_t size)

{

return malloc(size);

}

void delete[] (void *p)

{

free(p);

}

};

int main()

{

A *pa;

pa=new A;

delete pa;

pa=new A[10];

delete [] pa;

return 0;

}

Конструкторы преобразования и операции привидения типа.

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

Он позволяет преобразовать объект чужого типа в объект нашего класса. Тип аргумента конструктора и является преобразуемым чужим типом.

int i=10;

A(i)

void f(A x);

int main()

{

f(10);

}

class A

{

int a;

public:

explicit A(int x=0)

{

(*) a=x;

}

int get A() {return a;}

void set A(int x) {a=x;}

};

void f (double);

f (1);

A b (10); //нет преобразования

Сейчас конструктор А может использоваться в 2-х случаях:

  1. как обычный конструктор, вызываемый для инициализации вновь созданного объекта.

  2. как конструктор преобразования целого значения в объект класса А.

explicit используется для конструкторов преобразования, но запрещает использовать конструктор, как конструктор преобразования (кроме С++11).

Операция привидения типа.

А а(10);

int i;

i=(int)a; -> a.operator int() &a this /*выполнить такую операцию привидения типа можно только, если в классе А разрешено привидение типа к int (целому)*/

i=(int) 1.73;

(*)

operator int

return a;

}

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

Пример: класс представляющий двусвязный список.

Возможными понятиями являются:

  1. узел списка

struct ListNode

{

int key;

char *data;

ListNode *prev;

*next;

};

  1. список

class List

{

struct ListNode

{

int key;

char *data;

ListNode *prev;

*next;

};

ListNode *first;

public:

List() {first=0;}

~List() {delist ();}

void add (int key, char *data);

};

Обычно пользователю класса List не нужно знать о существовании ListNode, тогда можно спрятать ListNode в класс List (важно в какую секцию).

Константные поля и константные объекты класса.

class A

{

int a;

const int b;

public:

A(int _a=0, int _b=0) : b(_b), a(_a)

{

//a=_a;

(x) b=_b; /*по синтаксису С++ это попытка изменить значение константы*/

/*Константные поля получают свои значения в списке инициализации конструктора.

Список инициализации можно задавать только для конструкторов класса*/

};

/*Ссылки в С++ ведут себя как константы*/

int x=5;

int &ri=x;

/*Если полем класса является ссылка, то она инициализируется в списке инициализации конструкторов*/

A a1(-1, 2025), a2(10), //b=2025, b=10

a3; //b=10

Есть такие поля и методы, которые принадлежат классу в целом.

Константные объекты.

const A a;

Объект любого класса можно создать, как константный.

class A

{

int a;

mutable int b;

public:

A(int _a=0, int b=0) : ()b(_b), a(_a)

{ }

int get A() {return 0;}

void set A(int x) {a=x;}

int get B() const

{return b;}

void set A(int x) const

{b=x;}

};

Int main()

{

const A a;

(x) x=a.get B(); // разрешено

(x) a.set B(125); // разрешено

(x) a.set A(-1);

};

  1. Для константных объектов разрешен вызов только константных методов.

  2. Константный метод в общем случае не может изменять значение полей класса.

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

mutable – модификатор, задаваемый при изменении полей класса. Такие поля могут изменяться в константных методах.

Поля и методы класса в целом.

Int main()

{

A a1, a2;

Обычно поля, похожие на a и b в примере существуют только для каких-нибудь объектов класса.

Каждый объект обладает собственными копиями всех полей класса. Поэтому такие поля называют полями объектов класса.

a1.set A(-20);

a2.set A(20);

Обычные методы класса, подобные getA и setA не могут вызываться сами по себе, как внешние функции, а вызываются только для объектов класса. Их называют методами объектов класса.

Можно создавать такие поля и методы, которые не будут привязаны к конкретным объектам класса. Их называют полями и методами класса в целом. Такие поля и методы объявляются с помощью модификатора static.

class A

{

int a; // обычное поле класса

static int sa; /* поле класса в целом существует в единственном экземпляре, независимо от того, сколько объектов класса создано (даже если их нет). Статические поля хранятся в сегменте данных вместе с глобальными и статическими переменными*/

public: static int sa;

A(int x=0) : a(x) {}

void test()

{

cout<<”a=”<<a<<\’t’<<”sa=”<<sa<<endl;

};

/*Пока задано только описание поля sa, память для нее не выделена*/

int A:: sa; // int A:: sa=1;

Int main()

cout<<A:: sa<<endl;

A:: sa=-100;

A a1;

(x) a1.a=-1;

По умолчанию статические поля обнуляются.

class B

{

static cons tint b=10;

};

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

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

Пример:

class A

{

int a;

static int sa;

public:

A(int x=0) : a(x) {}

int getA() {return a;}

void setA (int x) {a=x;}

static int getSA() {return sa;}

static void setSA (int x)

{

sa=x;

??? a=x+1;

};

int A::sa=1;

Int main()

{

int i=A::getSA();

Статическим методам не передается скрытый аргумент this и это позволяет вызывать их при отсутствии экземпляров класса.

Статические методы можно вызывать, указывая объект класса, но this все равно передаваться не будет.

class A

{

int a;

A(int x=0) : a(x) {}

~A(){} A(A&x) {}

public:

int getA() {return a;}

void setA (int x) {a=x;}

};

Int main()

{

A a1, a2(-100); // нельзя

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

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

singleton – одиночка (один класс).

Если конструкторы закрытые, для создания объектов нужно использовать либо открытый метод класса, либо внешнюю функцию, если в ней есть доступ к закрытому методу класса (в С++ дружественная функция). Такие методы или функции называют фабрикой объектов класса.

static: A create (int x=0)

{

return *new A(x);

}

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

A a1=A:: create (100); //вызов конструктора копирования

Нужно закрыть конструктор копирования.

A *pa;

pa=A::create(100);

pa->setA(-100);

}

static destroy (A *p)

{

delete p;

}

A::destroy (pa);

То же самое можно сделать для ссылки.

Общая структура программы на С++.

#include <iostream>

using namespace std;