Ещё раз взгляните на объявление объектов класса student из приведённого выше примера:
Student noName ;
Student freshMan( "Smell E. Fish" ) ;
Student xfer( "Upp R. Classman" , 80 , 2.5 ) ;
Все объекты типа student , за исключением noName , объявлены со скобками, в которых находятся передаваемые классу аргументы. Почему же объект noName объявлен без скобок? С точки зрения приверженцев последовательности и аккуратности, лучше было бы объявлять этот объект так:
Student noName( ) ;
Конечно, можно сделать и так, но это не приведёт к ожидаемому результату. Вместо объявления объекта noName , создаваемого с помощью конструктора по умолчанию для класса student , будет объявлена функция, возвращающая по значению объект класса student . Мистика! Приведённые ниже два объявления демонстрируют, как похожи объявления объекта и функции в формате С++. ( Я-то считаю, что это можно было сделать и по-другому, но кто будет со мной считаться?.. ) Единственное отличие заключается в том, что при объявлении функции в скобках стоят названия типов, а при объявлении объекта в скобках содержатся объекты.
Student thisIsAFunc( int ) ;
Student thisIsAnObject( 10 ) ;
Если скобки пусты, невозможно однозначно сказать, что объявляется — функция или объект. Для обеспечения совместимости с языком С в С++ считается, что объявление с пустыми скобками — это объявление функции ( более надёжной альтернативой было бы требование наличия ключевого слова void при объявлении функции, но тогда нарушалось бы условие совместимости с существующими программами на С... ).
♦♦♦♦♦
►Конструирование членов класса...204
В предыдущих примерах использовались данные-члены простых типов, такие как float или int . Переменные таких простых типов легко инициализировать, передав необходимое значение конструктору. Но что, если класс содержит данные-члены, которые являются объектами других классов? Рассмотрим приведённый ниже пример.
/* ConstructingMembers — передача параметров */
/* конструктору члена */
#include
#include
#include
#include
using namespace std ;
const int MAXNAMESIZE = 40 ;
int nextStudentId = 0 ;
class StudentId
{
public :
StudentId( )
{
value = ++nextStudentId ;
cout << "Присвоение id " << value << endl ;
}
protected :
_________________
204 стр. Часть 3. Введение в классы
int value ;
} ;
class Student
{
public :
Student( char* pName )
{
cout << "Конструктор Student( " << pName
<< " )" << endl ;
strncpy( name , pName , MAXNAMESIZE ) ;
name[ MAXNAMESIZE - 1 ] = '\0' ;
semesterHours = 0 ;
gpa = 0.0 ;
}
/* ...прочие открытые члены... */
protected :
char name[ MAXNAMESIZE ] ;
int semesterHours ;
float gpa ;
StudentId id ;
} ;
int main( int argcs , char* pArgs[ ] )
{
setlocale ( LC_ALL , ".1251" ) ; /* печать кириллицы */
Student s( "Chester" ) ;
/* Пауза для того, чтобы посмотреть на результат работы программы */
system( "PAUSE" ) ; return 0 ;
}
В момент создания объекту типа Student присваивается собственный идентификатор. В данном примере идентификаторы "раздаются" последовательно, с помощью глобальной переменной nextStudentId .
Наш класс Student содержит член id , который является экземпляром класса StudentId . Конструктор класса Student не может присвоить значение члену id , поскольку Student не имеет доступа к защищённым членам класса StudentId . Можно было бы сделать Student другом класса StudentId , но такой подход нарушил бы положение объектно-ориентированного программирования, утверждающее, что каждый класс должен заниматься своим делом. Нам нужна возможность вызывать конструктор класса StudentId в процессе создания класса Student .
С++ делает это автоматически, инициализируя член id с помощью конструктора по умолчанию StudentId::StudentId( ) . Это происходит после вызова конструктора класса Student , но до того, как управление передаётся первой строке этого конструктора. ( Выполните в пошаговом режиме приведённую выше программу, и вы поймёте, о чём я говорю. ) Выполнение приведённой выше программы выведет на экран следующие строки:

Присвоение id 1
Конструктор Student( Chester )
Press any key to continue...
Обратите внимание: сообщение от конструктора StudentId появилось раньше, чем сообщение от конструктора Student . ( Поскольку у нас все конструкторы выводят информацию на экран, вы можете решить, что они всегда должны поступать подобным образом. На самом деле подавляющее большинство конструкторов работают "молча". )
Читать дальше