_________________
205 стр. Глава 17. Аргументация конструирования
Если программист не обеспечит свой класс конструктором, то конструктор по умолчанию, созданный С++, вызовет конструкторы всех данных-членов для их инициализации. То же касается и уничтожения объекта. Деструктор класса автоматически вызывает деструкторы всех данных-членов ( у которых они определены ).
Теперь мы знаем, что будет с конструктором по умолчанию. Но что, если мы захотим вызвать другой конструктор? Куда в этом случае нужно поместить объект? Я имею в виду следующее: представьте себе, что вместо автоматической генерации идентификатора студента, необходимо передать его конструктору Student , который в свою очередь, должен передать его конструктору StudentId .

«Для начала я покажу вам способ, который работать не будет. ( Здесь приведена только существенная для понимания часть кода — полностью программаConstructSeparateID.cpp находится на прилагаемом компакт-диске . )»
[ Диск ]
class Student
{
public :
Student( char *pName = "no name" , int ssId = 0 )
{
cout << "Конструктор Student( " << pName
<< " )" << endl ;
strncpy( name , pName , MAXNAMESIZE ) ;
name[ MAXNAMESIZE - 1 ] = '\0' ;
semesterHours = 0 ;
gpa = 0.0 ;
/* Вот это можно и не пытаться делать - толку не будет */
StudentId id( ssId ) ;
}
protected :
char name[ MAXNAMESIZE ] ;
StudentId id ;
} ;
Конструктор класса StudentId был переписан так, чтобы он мог принимать внешнее значение ( значение по умолчанию необходимо для того, чтобы приведённый фрагмент откомпилировался без ошибок, которые появятся в противном случае; почему — станет понятно чуть позже ). Внутри конструктора Student программист ( т.е. я ) попытался невиданным доселе способом сконструировать объект id класса StudentId .
Если вы внимательно посмотрите на сообщения, которые выдаются в результате работы этой программы, то поймёте, в чём проблема.

Присвоение id 0
Конструктор Student( Chester )
Присвоение id 1234
Деструктор id 1234
Сообщение из функции main( )
Press any key to continue...
Деструктор id 0
Первая проблема заключается в том, что конструктор класса StudentId вызывается дважды: сначала с нулём и только затем с ожидаемым числом 1234. Кроме того, объект с идентификатором 1234 ликвидируется перед выводом сообщения от main( ) . Очевидно, объект класса StudentId ликвидируется внутри конструктора класса Student .
_________________
206 стр. Часть 3. Введение в классы
Объяснить такое странное поведение программы довольно просто. Член id уже существует к моменту перехода управления к телу конструктора Student . Поэтому вместо инициализации уже существующего члена id объявление в последней строке конструктора Student вызывает создание локального объекта с таким же именем. Этот локальный объект и уничтожается при выходе из конструктора.

«Очевидно, нужен некий механизм конструирования не нового объекта, а уже существующего. Этот механизм должен работать перед открытием фигурной скобки конструктора. Для этого в С++ определена конструкция, использованная в программеConstructDataMember .»
[ Диск ]
//
/* ConstructDataMember — передача параметра */
/* конструктору члена */
//
#include
#include
#include
#include
using namespace std ;
const int MAXNAMESIZE = 40 ;
class StudentId
{
public :
StudentId( int id = 0 )
{
value = id ;
cout << "Присвоение id " << value << endl ;
}
~StudentId( )
{
cout << "Деструктор id " << value << endl ;
}
protected :
int value ;
} ;
class Student
{
public :
Student( char *pName = "no name" , int ssId = 0 )
: id( ssId )
{
cout << "Конструктор Student( " << pName
<< " )" << endl ;
strncpy( name , pName , MAXNAMESIZE ) ;
name[ MAXNAMESIZE - 1 ] - '\0' ;
}
protected :
char name[ 40 ] ;
StudentId id ;
} ;
int main( int argcs , char* pArgs[ ] )
{
setlocale ( LC_ALL , ".1251" ) ; /* печать кириллицы */
Student s( "Chester" , 1234 ) ;
cout << "Сообщение из функции main" << endl ;
Читать дальше