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

3. Объект.

Класс – это тип данных, а не объект.

Определение. Объект это переменная, тип которой – класс, и определяется он обычным образом.

void main()

{String s1, s2, *s3; // s1, s2 – объекты, s3 – указатель на объект.

}

Говорят также, что s1, s2 – экземпляры класса. Для каждого из них отведена будет память по 255 + 4 байтов.

Заметим, что указатель s3 пока не определен, т.е. там грязь.

Посмотрим, как мы теперь можем работать с объектами.

s1.Fill(“объект”);

s2.Fill(“ класса String ”);

s1[0] = ’O’; // ошибка: s1 – это не массив, и операция [] в нем не определена!

s1.line[0] = ‘O’; // опять ошибка: line – приватное ч/данное, в main использовать нельзя!

s1.Index(0) = ‘О’; // Это верно – пока только так, через ч/функцию, можно «добраться» до символа строки

cout << s1.len; // ошибка: len – приватное член-данное

cout << s1.Length(); // так можно получить длину строки

s3 = &s1; // s3 – указатель на строку s1

s3 –> Index(0) = ‘O’; // используя функцию Index(int), заменим еще раз букву ‘о’ на ’О’

s3 –> Print(); // вывод слова «Объект»

s3 = &s2; // теперь s3 – указатель на объект s2

s3 –> Index(s3 –> Length() - 1) = ‘.’; // Используя член-функции класса Length() и Index()

// поставим в конце строки s3 символ '.'

s3 –> Print(); // вывод фразы « класса String.»

s3 = new String(«Динамическая память»); // определяется объект в динамической памяти

4. Конструкторы и деструкторы

4.1.Назначение конструктора

В С++ при определении переменных часто их сразу инициализируют, например,

int x = 5;

Предположим, что при определении объекта

String s;

мы хотели бы проинициализировать его, например, пустой строкой:

len = 0; line[0] = ’\0’.

Для структур эта инициализация выполняется так:

String s = {“”, 0};

Для объектов класса такая инициализация запрещена в силу принципа инкапсуляции.

Поэтому и возникает проблема: внутри описания класса инициализировать нельзя по синтаксису языка, но и вне класса записать

s.len = 0; s.line[0] = ’\0’;

тоже нельзя, т.к. член-данные из части private недоступны. (Заметим, что если определить их в части public, то их можно инициализировать таким образом

String s = {«», 0};

то есть как структуру)

Следовательно, инициализацию должна выполнять специальная член-функция класса.

Определение. Член-функция класса, предназначенная для инициализации член-данных класса при определении объектов класса, называется конструктором. Конструктор всегда имеет имя класса.

Для решения нашей задачи можно записать такой конструктор

Strring:: String( ) { len = 0; line[0] = ’\0’;} (1)

объявив его обязательно в теле класса следующим образом:

String( );

Тогда при определении объектов, например,

String s1, s2;

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

В классе можно задать не один конструктор, а несколько. Для класса String можно задать конструктор с аргументом, аналогичный функции Fill( ).

String:: String(const char * s)

{for(len = 0; line[len] != ‘\0’; line[len] = s[len], len++);

line[len] = ‘\0’;}

Тогда объекты можно определить таким образом:

String s1, s2(«Иванов»), *s3 = new String(«Петров»);

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

Особенности конструктора, как функции:

  1. Главная – конструктор не имеет возвращаемого значения (даже void), так как его назначение – инициализировать собственные член-данные объекта;

  2. Конструктор имеет имя класса;

  3. Конструктор работает неявно при определении объектов класса.

Недостаток определенного класса String – это то, что он берет для каждого объекта 257 байтов памяти, хотя фактически использует меньше.

Изменим определение класса String таким образом:

class String { char *line; int len;

public:

....

}

;

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

Зададим такие конструкторы.

В классе объявим 2 конструктора:

String(int I = 80); // с аргументом по умолчанию

String(const char *); // с аргументом строкой

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

String:: String(int l) // l = 80 – не повторять! (2)

{line = new char[l]; len = 0;

line[0] = ’\0’;

}

String:: String(const char * s)

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

for(len = 0; line[len] != ‘\0’; line[len] = s[len], len++);

line[len] = ‘\0’;

}

Эти конструкторы можно использовать таким образом:

String s1(10), s2, s3(«без слов»);

Заметим, что в классе должен быть или конструктор по умолчанию без аргументов (вида (1)), или конструктор по умолчанию с аргументом по умолчанию (вида (2)). В противном случае, следующее определение:

String ss;

вызовет сообщение о двусмысленности.

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]