Оператор присвоения очень похож на конструктор копирования, а при использовании они практически идентичны.
void fn( MyClass&mc )
{
MyClass newMC( mc ) ; /* Здесь используется конструктор копирования */
MyClass newerMC = mc ; /* Менее очевидно, что здесь также используется конструктор копирования */
MyClass newestMC ; /* Создание объекта по умолчанию */
newestMC = mc ; /* Присвоение */
}
_________________
272 стр. Часть 5. Полезные особенности
Создание newMC следует стандартному шаблону создания нового объекта как зеркального отображения существующего с использованием копирующего конструктора MyClass( MyClass& ). Несколько менее очевидно, что объект newerMC также создаётся при помощи конструктора копирования. Запись MyClass а = b — всего лишь другой способ записи MyClass a( b ). То, что в первом варианте записи имеется символ "=", не приводит к вызову оператора присвоения. Однако в случае с объектом newestMC всё не совсем так. Сначала этот объект создаётся с использованием конструктора по умолчанию, а затем перезаписывается объектом mc с помощью оператора присвоения.
Подобно конструктору копирования, оператор присвоения должен быть переопределён, если мелкое копирование приводит к некорректным результатам ( см. материал, представленный в главе 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 ;
}
}