Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
ООП_Лаб.работа №3.doc
Скачиваний:
0
Добавлен:
01.07.2025
Размер:
139.78 Кб
Скачать

Конструкторы копирования.

Копирующий конструктор позволяет производить копирование одного объект класса в другой объект того же класса. Эта операция необходима в следующих случаях:

  • Вновь создаваемый объект класса должен стать копией уже имеющегося объекта (инициализация копированием).

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

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

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

В следующем примере работает копирование по-умолчанию.

#include "stdafx.h"

#include <iostream>

#include <stdlib.h>

using namespace std;

class MyStr

{ ...

...

};------- конец определения класса MyStr

int MyStr::count=0;

int MyStr::num=0;

int main(int argc, char* argv[])

{ MyStr c1("1_string"); // создание объекта с1

cout<<endl<<"Объект с1"<<endl;

c1.display();

MyStr c2(c1); // создание объекта с2 (инициализация копированием)

cout<<"Объект с2"<<endl;

c2.display();

MyStr c3=c1; // создание объекта с3 и присвоение ему значения с1

cout<<"Объект с3"<<endl;

c3.display();

system ("pause");

return 0;

}

Строка MyStr c2(c1) вызывает конструктор копирования (во вновь создаваемый объект с2 записывается информация из с1). В строке MyStr c3=c1 оператор присваивания вызывает конструктор копирования.

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

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

Добавим в класс MyStr копирующий конструктор:

MyStr(MyStr& s)

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

num++;

count++;

nn=num;

strcpy(buf, s.buf);

}

В результате программа полностью корректно работает.

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

MyStr c2(c1); - активный объект с2, пассивный с1

MyStr c3=c1; - активный объект с3, пассивный с1

Обратите внимание на тип аргумента копирующего конструктора – это всегда ссылка на свой класс, ссылка на пассивный объект.

Работа копирующего конструктора при передаче объекта класса в качестве параметра функции (и возврате из функции объекта класса) будет рассмотрена позднее.

Друзья класса

Для того, чтобы предоставить легкий доступ к данным класса механизм с помощью ключа public не всегда удобен, ведь в этом случае public-переменные становятся общедоступны, то есть к ним может обратиться кто угодно из любой части программы. Механизм под названием «друзья класса» действует более гибко и позволяет предоставлять доступ избирательно. Например, можно предоставить доступ к закрытым переменным класса только для какой-либо функции или класса.

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

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

Дружественная функция имеет два параметра , первый – ссылка на объект класса MyStr в который будет производиться ввод, второй - ограничитель ввода (максимальное число символов в строке). Описание дружественной функции размещаем в глобальной области программы.

#include "stdafx.h"

#include <iostream>

#include <stdlib.h>

using namespace std;

class MyStr

{ static int count; // счетчик существующих строк

char *buf; // закрытые данные

// прототип дружественной функции

friend void inpstr(MyStr&, int );

public:

static int num; // счетчик порядкового номера

int nn; // порядковый номер строки

}; // конец определения класса

int MyStr::count=0;

int MyStr::num=0;

// определение дружественной функции

void inpstr(MyStr& s, int n)

{ char* fs; // указатель для доступа к дин.памяти

fs= new char[n+1]; // получение дин. памяти

cout<<"ввод с клавиатуры:"; // «приглашение» для ввода

cin>>fs;

strcpy(s.buf,fs); // копирование строки в закрытую область объекта класса

}

int main(int argc, char* argv[])

{MyStr c1("1_string"); // создание объекта с1

cout<<endl<<"Объект с1"<<endl;

c1.display();

MyStr c2(c1); // создание объекта с2 (инициализация копированием)

cout<<"Объект с2"<<endl;

c2.display();

MyStr c3=c1; // создание объекта с3 и присвоение ему значения с1

cout<<"Объект с3"<<endl;

c3.display();

cout<<"c1-"; // отображаем объект ввода

inpstr(c1,10); // вызов дружественной функции

cout<<"новый Объект с1"<<endl;

c1.display();

system ("pause");

return 0;

}

До сих пор мы решали задачи с использованием отдельных экземпляров класса, но для создания баз данных необходимы массивы объектов класса.

Создавая массивы объектов, например MyStr V[10], нам потребуется конструктор с инициализацией по-умолчанию. Такой конструктор может выглядеть, например так:

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

MyStr()

{ num++; // при создании объекта счетчики наращиваются

count++;

nn=num;

// по-умолчанию выделяется строка под 60 символов

buf= new char[60];

buf="free"; // константная строка

}

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

class MyStr

{…

// метод для вывода данных объекта в табличном виде

void display_tab()

{ cout<<nn<<'\t'<<buf<<endl;

}

}; // конец определения класса

int main(int argc, char* argv[])

{const int n=15;

int i;

// массив объектов, инициализируемых по-умолчанию

MyStr V[n];

// заголовок таблицы

cout<<" п/п \t строка"<<endl;

cout<<"------------------------"<<endl;

// цикл для вывода данных таблицы

for (i=0;i<n;i++) V[i].display_tab();

cout<<"Общее число записей = "<<V[0].get_count()<<endl;

system ("pause");

return 0;

}