Студопедия

КАТЕГОРИИ:


Архитектура-(3434)Астрономия-(809)Биология-(7483)Биотехнологии-(1457)Военное дело-(14632)Высокие технологии-(1363)География-(913)Геология-(1438)Государство-(451)Демография-(1065)Дом-(47672)Журналистика и СМИ-(912)Изобретательство-(14524)Иностранные языки-(4268)Информатика-(17799)Искусство-(1338)История-(13644)Компьютеры-(11121)Косметика-(55)Кулинария-(373)Культура-(8427)Лингвистика-(374)Литература-(1642)Маркетинг-(23702)Математика-(16968)Машиностроение-(1700)Медицина-(12668)Менеджмент-(24684)Механика-(15423)Науковедение-(506)Образование-(11852)Охрана труда-(3308)Педагогика-(5571)Полиграфия-(1312)Политика-(7869)Право-(5454)Приборостроение-(1369)Программирование-(2801)Производство-(97182)Промышленность-(8706)Психология-(18388)Религия-(3217)Связь-(10668)Сельское хозяйство-(299)Социология-(6455)Спорт-(42831)Строительство-(4793)Торговля-(5050)Транспорт-(2929)Туризм-(1568)Физика-(3942)Философия-(17015)Финансы-(26596)Химия-(22929)Экология-(12095)Экономика-(9961)Электроника-(8441)Электротехника-(4623)Энергетика-(12629)Юриспруденция-(1492)Ядерная техника-(1748)

Константные объекты и функции-члены

Инициализация переменных-членов в конструкторах

При определении класса запрещается инициализировать переменные-члены. Так, следующее определение класса содержит ошибки.

class С { private:int N = 0; //ОШИБКАconst int CInt = 5; //ОШИБКАint &RInt = N; //ОШИБКА//...};

Инициализация переменных внутри определения класса бессмысленна, потому что определение класса задает всего лишь тип каждой из переменных-членов, но не резервирует для них реальную область памяти. Скорее всего, при написании программы требуется инициализировать переменные-члены каждый раз при описании экземпляра класса. Следовательно, целесообразно инициализировать переменные внутри конструктора класса. Конструктор класса CRectangle инициализирует переменные-члены, используя выражение присваивания. Однако определенным типам данных, в частности, константам и ссылкам, не могут быть присвоены значения. Чтобы эта проблема не возникала, в языке C++ предусмотрено специальное свойство конструктора, называемое списком инициализации, который позволяет инициализировать одну или более переменных, а не присваивать им значения.

Список инициализации в определении конструктора помещается непосредственно после списка параметров. Он содержит двоеточие с последующим одним или несколькими инициализаторами полей, отделенными друг от друга запятыми. Инициализатор поля содержит имя переменной с последующим начальным значением в круглых скобках. Например, в приведенном ниже классе конструктор содержит список инициализации, который, в свою очередь, содержит инициализаторы полей для всех переменных класса.

class С{private:int N;const int CInt;int &RInt;//... public:С (int Parm): N (Farm), CInt (5), RInt (N){

// код конструктора...

}//...};

Следующее определение создает объект, демонстрирующий применение списка инициализации, где переменные N и CInt инициализированы значениями 0 и 5, а переменная-член RInt – как ссылка на переменную N:

С CObject (0);

Как показано в гл. 2, добавление спецификатора const к определению переменной означает невозможность изменения ее значения. Аналогично, добавление спецификатора const в определение объекта класса означает, что нельзя изменять значения переменных, принадлежащих этому классу. Рассмотрим, например, класс

class CTest {public:int A; int B;CTest (int AVal, int BVal); {

A = AVal;

В = BVal;

} }

Оператор создает объект этого класса и инициализирует обе переменные-члены

const CTest Test (1, 2};

Это первая и последняя возможность присвоить значения таким переменным. Из-за спецификатора const недопустимо присваивание

Test.А =3; // ОШИБКА: нельзя изменять переменные-члены //Объекта типа const

Существуют и другие варианты объявления объекта с использованием спецификатора const. Чтобы продемонстрировать их, рассмотрим объявление объекта класса CRectangle, приведенного в этой главе.

const CRectangle Rect (5, 5, 25, 25);

Хотя функция-член GetCoord класса CRectangle не изменяет никаких переменных-членов, компилятор не позволит программе вызвать ее для объекта с атрибутом const.

int L, Т, R, В;Rect.GetCoord (&L, &T, &R, &B); //ошибка

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

Чтобы иметь возможность вызова функции GetCoord для объекта типа const, следует включить спецификатор const в определение функции.

class CRectangle{//...void GetCoord (int *L6 int *T6 int *R, int *B) const{

*L = Left;

*T = Top;

*R = Right;

*B = Bottom;

}//...};

Спецификатор const в определении функции GetCoord означает, что функция не может изменять переменные-члены. Если она пытается это сделать, компилятор будет генерировать ошибку при компиляции исходного кода. Функцию GetCoord сейчас можно вызвать для объекта типа const класса CRectangle.

const CRectangle Rect (5, 5, 25, 25); int L, T, R, B;Rect.GetCoord (&L, &T, &R, &B); //допустимо: функция GetCoord // объявлена как const

Кроме того, можно функцию-член Draw объявить как const, так как она не изменяет значений переменных. Очевидно, имеет смысл добавлять спецификатор const ко всем функциям-членам, которые не модифицируют поля класса, чтобы пользователь мог свободно вызывать такие функции для объектов типа const. Конечно, функцию, подобную CRectangle:: SetCoord, нельзя объявить как const.

Инициализация объектов-членов класса. Можно определить переменную, являющуюся объектом другого класса, т. е. можно встроить объект одного класса в объект другого. Такие переменные называют объектами-членами или встроенными объектами. Его можно инициализировать, передавая требуемые параметры конструктору, помещенному в список инициализации конструктора класса, содержащего объект-член. Например, класс CContainer в следующем примере содержит объект-член класса CEmbedded, инициализируемый в конструкторе класса CContainer.

class CEmbedded {//...public:CEmbedded (int Parml, int Parm2) {

//...

}//...};class CContainer{private:CEmbedded Embedded; public:CContainer (int PI, int P2, int P3): Embedded (PI, P2) {

// код конструктора...

}//... };

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

Примечание

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

<== предыдущая лекция | следующая лекция ==>
Перегруженные конструкторы | Массивы объектов
Поделиться с друзьями:


Дата добавления: 2014-01-07; Просмотров: 1293; Нарушение авторских прав?; Мы поможем в написании вашей работы!


Нам важно ваше мнение! Был ли полезен опубликованный материал? Да | Нет



studopedia.su - Студопедия (2013 - 2024) год. Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав! Последнее добавление




Генерация страницы за: 0.013 сек.