|
Программирование >> Инициализация объектов класса, структура
(c) class iMatrix { public: ... private: int rows; int cols; int * matrix; (d) class theBigx { public: ... private: BinStrTree bst; iMatrix im; string name; vectorMfloat> * pvec; Упражнение 14.15 Нужен ли копирующий конструктор для того класса, который вы выбрали в упражнении 14.3 из раздела 14.2? Если нет, объясните почему. Если да, реализуйте его. Упражнение 14.16 Идентифицируйте в следующем фрагменте программа: все места, где происходит Point global; Point foo bar( Point arg ) Point local = arg; Point *heap = new Point( global ); *heap = local; Point pa[ 4 ] = { local, *heap }; return *heap; почленная инициализация: 14.7. Почленное присваивание A Присваивание одному объекту класса значения другого объекта того же класса реализуется почленным присваиванием по умолчанию. От почленной инициализации по умолчанию оно отличается только использованием копирующего оператора присваивания вместо копирующего конструктора: newAcct = oldAcct; inline Accounts Account:: operator=( const Account srhs ) { name = rhs. name; balance = rhs. balance; acct nmbr = rhs. acct nmbr; оператор присваивания: Как правило, если для класса не подходит почленная инициализация по умолчанию, то не подходит и почленное присваивание по умолчанию. Например, для первоначального определения класса Account, где член name был объявлен как char*, такое присваивание не годится ни для name, ни для acct nmbr. Мы можем подавить его, если предоставим явный копирующий оператор присваивания, общий вид classNames копирующего оператора присваивания className:: operator=( const className srhs ) { не надо присваивать самому себе if ( this != srhs ) { здесь реализуется семантика копирования класса вернуть объект, которому присвоено значение return *this; где будет реализована подходящая для класса семантика: Здесь условная инструкция if ( this != srhs ) предотвращает присваивание объекта класса самому себе, что особенно неприятно в ситуации, когда копирующий оператор присваивания сначала освобождает некоторый ресурс, ассоциированный с объектом в левой части, чтобы назначить вместо него ресурс, ассоциированный с объектом в правой части. Рассмотрим копирующий оператор присваивания для класса Account: по умолчанию присваивает каждому нестатическому члену newAcct значение соответственного члена oldAcct. Компилятор генерирует следующий копирующий Accounts Account:: operator=( const Account srhs ) { не надо присваивать самому себе if ( this != &rhs ) delete [] name; name = new char[strlen(rhs. name)+1]; name strcpy( name,rhs. name ); balance = rhs. balance; acct nmbr = rhs. acct nmr; return *this; Когда один объект класса присваивается другому, как, например, в инструкции: newAcct = oldAcct; выполняются следующие шаги: 1. В1ясняется, есть ли в классе явный копирующий оператор присваивания. 2. Если есть, проверяются права доступа к нему, чтобы понять, можно ли его вызывать в данном месте программы. 3. Оператор вызывается для выполнения присваивания; если же он недоступен, компилятор выдает сообщение об ошибке. 4. Если явного оператора нет, выполняется почленное присваивание по умолчанию. 5. При почленном присваивании каждому члену встроенного или составного члена объекта в левой части присваивается значение соответственного члена объекта в правой части. 6. Для каждого члена, являющегося объектом класса, рекурсивно применяются шаги 16, пока не останутся только члены встроенных и составных типов. Если мы снова модифицируем определение класса Account так, что name будет иметь тип string, то почленное присваивание по умолчанию newAcct = oldAcct; будет выполняться так же, как при создании компилятором следующего оператора inline Accounts Account:: operator=( const Account srhs ) { balance = rhs. balance; acct nmr = rhs. acct nmbr; этот вызов правилен и с точки зрения программиста name.string::operator=( rhs. name ); присваивания:
|
© 2006 - 2024 pmbk.ru. Генерация страницы: 0.001
При копировании материалов приветствуются ссылки. |