    TAnyClass::TAnyClass(TAnyClass &copy) { 
    cout « "Inside TAnyClass1s copy constructor\n"; 
    i = copy.i; 
    r = copy. r; 
    if (copy.s) 
       s = strdup(copy.s); 
    else	
       s = NULL; 
    } 

    Можно обойтись и без оператора вывода в поток. Конечно, при отладке это 
отображение момента запуска конструктора приносит свою пользу. Следующие два 
оператора копируют члены i и г из сору в новый объект. Чтобы можно было 
обрабатывать строку, на которую ссылается указатель s, с помощью функции 
strdup( выделяется еще один участок памяти в куче для копии первоначальной 
строки. Или же, если в указателе объекта сору содержится нуль, указателю 
нового объекта присваивается NULL. Для скопированных объев класса TAnyClass 
более не существует опасности, что два или более указателей s будут случайно 
ссылаться на один и тот же участок памяти. Теперь в программе можно смело 
использовать следующие операторы: 

    TAnyClass v1; 
    TAnyClass v2(1.  2,   "A test string"); 
    TAnyClass v3 = v2;       // Вызывается конструктор копии 

    C++ автоматически вызывает конструктор копии класса TAnyClass в первых 
трех из четырех, перечисленных выше, ситуаций — когда объект использовался для 
инициализации только что созданного объекта класса TAnyClass (что 
иллюстрируется третьей строкой предыдущего примера), когда оператор передает 
объект параметру функции или когда функция возвращает объект класса. 
    К сожалению, использовать класс TAnyClass все еще небезопасно. Когда 
оператор непосредственно присваивает один объект другому, вы должны опять же 
изучить, что произойдет, если эти объекты содержат члены-указатели. В 
следующем разделе поясняется, как справиться с этой проблемой. 

    ЗАМЕЧАНИЕ 

    C++ также вызывает конструкторы копии для аргументов-объектов классов,  
передающихся по значению функции, а также, когда функции возвращают объекты классов. 

    Почленное присваивание 

    Присваивание объекта класса другому объекту может привести к тому, что 
члены-указатели на данные будут ссылаться на один и тот же участок памяти; это 
опасная ситуация, которую необходимо устранить любой ценой. Рассмотрим 
следующий фрагмент программы, в котором используется класс TAnyClass из 
предыдущего раздела: 

    TAnyClass v1; 
    TAnyClass v2(1, 2, "A test string"); 
    v1 = v2;    // ??? 

    После инициализации объекта v1 значениями по умолчанию и определения v2 с 
явными аргументами оператор присваивания копирует v2 в v1. Но берегитесь! 
Присваивание не вызывает ни один из конструкторов класса, даже конструктор 
копии. Если в классе объявляются или наследуются члены-указатели на данные, 
скопированные указатели будут ссылаться на один и тот же участок памяти, что 
наверняка послужит причиной возникновения серьезных ошибок, если эта память 
удаляется деструктором. 
    Конструктор копии не решит этой проблемы, поскольку задействованные 
объекты уже созданы. C++ вызывает конструкторы в случае инициализации новых 
объектов, но не в случае присваивания одного объекта другому. 
    К счастью, вы можете легко разрешить вашу проблему, перегрузив оператор 
присваивания =. Следует использовать объявление вида 
                   
      void operator=(const CLASS&). 

Например, для перегрузки оператора присваивания в классе TAnyClass из 
предыдущего раздела модифицируйте его следующим образом: 

    class TAnyClass { 
    private: 
    int i;	II Закрытый член класса 
    double r; // Закрытый член класса 
    char *s; // Закрытый член-указатель! 
    public: 
       ......    // См. предыдущее объявление класса TAnyClass 
       void operator=(const TAnyClass &copy);    // Оператор присваивания 


    384    Часть III. Программирование на ANSI C++ 
