Программирование >>  Аргументация конструирования 

1 ... 57 58 59 [ 60 ] 61 62 63 ... 108


Компилятор сообщает, что он не может найти конструктор student: : Student (). Добавив конструктор по умолчанию, можно решить эту проблему:

class Student

public:

Studgnt (char *pName) ; Student();

int main(int argcs, char* pArgs[])

Student noName; return 0;

Это пример нелогичности, поясняющий, за что программистам на C + + платят

большие деньги.

MoHC0lfiifufto€aHue членовкласса

В предыдущих примерах использовались данные-члены простых типов, такие, как float или int. Переменные таких простых типов легко инициализировать, передав необходимое значение конструктору. Но что, если класс содержит данные-члены, которые являются объектами других классов? Рассмотрим приведенный ниже пример.

#include <io3tream.h> ttinclude <string.h>

int nextStudentId = 0; class Studentid

publie;

StudeiUtld ( )

value = 4nextStudentId;

coat << Присваиваем студенту идентификатор value \n ;

protected:

int value;

class Student

public:

Student (char pName no name )

c:out << Создаем студента << pName << \n :;tmcpY (name, pName, sizeof (name) ) ; nam f (name) - 1] = \0;

protected:

char name [40] ; Studentld id;

in i:int argcs, char* pArgs [ ] )



student s( Randy ); return 0;

В момент создания объекту тина student присваивается собственный идентификатор. В данном примере идентификаторы раздаются последопательно. с помощью глобальной переменной nextStuden: id.

Наш класс Student содержит член id. который является экземпляром класса Student Конструктор класса Student не может присвоить значение члену поскольку Student не имеет доступа к защищенным членам класса St.uder.tlD. Можно было бы сделать student другом класса но такой подход нарушил бы по-

ложение объектно-ориентированного программирования, утверждаюшес, что каждый класс должен заниматься своим делом. Нам нужна возможность вызывать конструктор класса StudentlDB процессе создания класса Student.

C++ делает это автоматически, инициализируя член id с помощью конструктора по умолчанию Student ID:: StudentiD (). Это нроисходит после вызова конструктора класса но до того, как управление передается первой строке этого конструкто-

ра. (Выполните в пошаговом режиме приведенную выше программу, и вы поймете, о чем я говорю. Только не забудьте при компиляции включить опцию Outline inline functions.) Выполнение приведенной выше программы выведет на экран следующие строки:

Присваиваем студенту таф-ккатор 1 Создаем студента Randy

Обратите внимание: сообщение от конструктора StudentiD появилось раньше, чем сообщение от конструктора Student.

(Поскольку у нас все конструкторы выполняют вывод на экран, вы можете решить, что они всегда должны поступать подобным образом. На самом деле подавляющее большинство конструкторов работают молча .)

Если программист не обеспечит свой класс конструктором, то конструктор по умолчанию, созданный C++, вызовет конструкторы всех данных-членов для их инициализации. То же касается и уничтожения объекта. Деструктор класса автоматически вызывает деструкторы всех данных-членов (которые, само собой, его имеют).

Теперь мы знаем, что будет с конструктором по умолчанию. Но что, если мы захотим вызвать другой конструктор? Куда в этом случае нужно поместить объект? Вот что я имею в виду: представьте себе, что вместо автоматической генерации идептифи-катора студента, необходимо передать его конструктору student с тем, чтобы он, в свою очередь, передал его конструктору

Для начала я покажу вам способ, который работать не будет.

#include <iostream.h> #include <string.h>

class Student Id

public:

id = 0)

value = id;

cout Присваиваем студен-у id, равный value \n ;

-Studentid ()

) cout << Удаляем студента << value << \n ;



protect:

int value

class Student {

public:

Student (char *pName = no name , in Id = 0)

cout Создаем студента pName \n ; scrncpy(name, pName, sizeof(name)); name[sizeof(name) - 1] = \0 ;

11 Вот это можно и не пытаться делать / / - толку не будет Studentld id(ssld);

protected:

char name[40) ; Studentld id;

in (int argcs, char* pArgs [) )

Student s( Randy , 1234); cout Сообщение из main\n ; return 0;

Конструктор класса был переписан так, чтобы он мог принимать

внешнее значение (значение но умолчанию необходимо для того, чтобы приведенный фрагмент откомпилировался без ошибок, которые в противном случае появятся; почему - станет понятно чуть позже). Внутри конструктора Student программист (т.е. я) попытался невиданным доселе способом сконструировать объект id класса

Если вы внимательно посмотрите на сообщения, которые выдаются в результате

работы этой программы, то поймете, в чем проблема,

Присваиваем студенту id, равный 0 Создаем студента Randy Присваиваем студенту id, равный 1234 Удаляем студента 12 34 Сообщение из main

Удаляем студента 0

Первая проблема заключается в том, что конструктор класса вызывает-

ся дважды: в первый раз с нулем и только затем с ожидаемым числом 1234. Кроме того, объект с идентификатором 1234 ликвидируется перед выводом сообщения от

main{). Очевидно, объект класса studentlD ликвидируется внутри конструктора класса Student.

Объяснить такое странное поведение программы довольно просто. Член id уже существует к моменту перехода управления к телу конструктора Поэтому

вместо инициализации уже существующего члена id объявление в последней строке конструктора Student вызывает создание локального объекта с таким же именем. Этот локальный объект и уничтожается при выходе из конструктора.

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



1 ... 57 58 59 [ 60 ] 61 62 63 ... 108

© 2006 - 2024 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки.
Яндекс.Метрика