Стефан Дэвис - С++ для чайников .
- Название:С++ для чайников .
- Автор:
- Жанр:
- Издательство:Издательский дом Вильямс. Компьютерное издательство Диалектика
- Год:2007
- Город:Москва
- ISBN:0-7645-6852-3, 978-5-8459-0723-3
- Рейтинг:
- Избранное:Добавить в избранное
-
Отзывы:
-
Ваша оценка:
Стефан Дэвис - С++ для чайников . краткое содержание
1
empty-line
4
С++ для чайников . - читать онлайн бесплатно полную версию (весь текст целиком)
Интервал:
Закладка:
Подобно конструктору копирования, оператор присвоения должен быть переопределён, если мелкое копирование приводит к некорректным результатам ( см. материал, представленный в главе 18, "Копирующий конструктор"). Простейшее правило: если у класса есть пользовательский конструктор копирования, то переопределите для него и оператор присвоения.
«Главное правило заключается в следующем: конструктор копирования используется при создании нового объекта, а оператор присвоения — если объект слева от символа присвоения уже существует.»
[ Советы ]
►Переопределение оператора присвоения...273
Следующая программа демонстрирует переопределение оператора присвоения. В программе также представлен конструктор копирования — просто для сравнения.
//
/* DemoAssignmentOperator — демонстрация оператора */
/* присвоения для пользовательского класса */
//
#include
#include
#include
#include
using namespace std ;
/* Name — класс для демонстрации присвоения и конструктора копирования */
class Name
{
public :
Name( char *pszN = 0 )
{
copyName( pszN , " " ) ;
}
Name( Name & s )
{
cout << "Вызов конструктора копирования" << endl ;
copyName( s.pszName , " ( copy ) " ) ;
}
~Name( )
{
deleteName( ) ;
}
/* Оператор присвоения */
Name & operator=( Name & s )
{
cout << "Выполнение присвоения" << endl ;
_________________
273 стр. Глава 23. Оператор присвоения
/* Удаляем выделенную память... */
deleteName( ) ;
/* ...перед заменой её новым блоком */
copyName( s.pszName , " ( replaced ) " ) ;
/* Возвращаем ссылку на существующий объект */
return *this ;
}
/* Очень простая функция доступа */
char* out( ) { return pszName ; }
protected :
void copyName( char* pszN , char* pszAdd ) ;
void deleteName( ) ;
char *pszName ;
} ;
/* copyName( ) — Выделение памяти из кучи и сохранение строк в ней */
void Name::copyName( char* pszN , char* pszAdd )
{
pszName = 0 ;
if ( pszN )
{
pszName = new char[ strlen( pszN ) +
strlen( pszAdd ) + 1 ] ;
strcpy( pszName , pszN ) ;
strcat( pszName , pszAdd ) ;
}
}
/* deleteName( ) — возврат памяти в куче */
void Name::deleteName( )
{
if ( pszName )
{
delete pszName ;
pszName = 0 ;
}
}
int main( int nNumberofArgs , char* pszArgs[ ] )
{
setlocale ( LC_ALL , ".1251" ) ; /* печать русских текстов */
/* Создание двух объектов */
Name n1( "Claudette" ) ;
Name n2( "Greg" ) ;
cout << "n1 ( " << n1.out( ) << " ) и "
<<"n2 ( " << n2.out( ) << " ) — "
<< "вновь созданные объекты"
<< endl ;
/* Конструктор копирования */
cout << "Name n3( n1 ) ;" << endl ;
Name n3( n1 ) ;
cout << "n3 ( " << n3.out( ) << " ) — копия n1" << endl ;
_________________
274 стр. Часть 5. Полезные особенности
/* Создание нового объекта с использованием формата с "=" для обращения к конструктору копирования */
cout << "Name n4 = n1 ;" << endl ;
Name n4 = n1 ;
cout << "n4 ( " << n4.out( ) << " ) — ещё одна копия n1"
<< endl ;
/* Перезапись n2 объектом n1 */
cout << "n2 = n1" << endl ;
n2 = n1 ;
cout << "n1 ( " << n1.out( ) << " ) присвоен объекту "
<< "n2 ( " << n2.out( ) << " )" << endl ;
/* Пауза для того, чтобы посмотреть на результат работы программы */
system( "PAUSE" ) ; return 0 ;
}
Класс Name содержит указатель на имя человека, которое записывается в блок памяти, выделяемый из кучи. Конструктор и деструктор класса Name аналогичны представленным в главах 17, "Аргументация конструирования", и 18, "Копирующий конструктор". Конструктор Name( char* ) копирует переданное ему имя в член pszName . Этот конструктор служит также в роли конструктора по умолчанию. Конструктор копирования Name( Name & ) копирует имя переданного объекта при помощи функции-члена copyName( ) . Деструктор освобождает блок памяти при помощи вызова deleteName( ) .
Оператор присвоения operator=( ) является методом класса. Он выглядит как деструктор, за которым тут же следует конструктор копирования, что представляет собой вполне типичную ситуацию. Рассмотрим присвоение n2 = n1 . Объект n2 уже имеет связанное с ним имя " Greg ". В процессе присвоения память, выделенная для этого имени, освобождается при помощи вызова deleteName( ) , так же, как это делается в деструкторе. Затем оператор присвоения вызывает copyName( ) для копирования новой информации в объект, подобно тому, как это делается в конструкторе копирования.
Конструктору копирования не нужно вызывать deleteName( ) , поскольку объект в этот момент ещё не существует, и память из кучи не выделена. Соответственно, деструктору не надо вызывать функцию копирования.
Есть ещё пара деталей, о которых следует упомянуть. Во-первых, возвращаемый оператором присвоения тип — Name &. Выражения, включающие оператор присвоения, имеют тип и значение, которые совпадают с типом и значением левого аргумента после присвоения. В следующем примере значение operator=( ) равно 2.0 , а его тип — double .
double d1 , d2 ;
void fn( double )
d1 = 2.0 ; /* Значение этого выражения равно 2.0 */
Это позволяет программисту написать следующее:
d2 = d1 = 2.0 ;
fn( d2 = 3.0 ) ; /* Выполняет присвоение и передаёт полученное значение функции fn( ) */
Значение присвоения d1 = 2.0 , равное 2.0, и его тип double передаются для присвоения d2 . Во втором примере значение присвоения d2 = 3.0 передаётся функции fn( ) .
Во-вторых, оператор присвоения является функцией-членом. Её левый аргумент — текущий объект ( this ). В отличие от других операторов, оператор присвоения не может быть перегружен при помощи функции — не члена класса.
_________________
275 стр. Глава 23. Оператор присвоения
►Защита от копирования...276
Оснащение вашего класса оператором присвоения может значительно повысить его гибкость. Однако, если это требует слишком большого объёма работы или вы не хотите, чтобы С++ создавал копии вашего объекта, перегрузка оператора присвоения защищённой функцией оградит вас от нежелательного мелкого почленного копирования.
class Name
{
/* ...всё, как и раньше... */
protected :
/* Конструктор копирования */
Name( Name & ){ } ;
/* Оператор присвоения */
Читать дальшеИнтервал:
Закладка: