|
Программирование >> Инициализация объектов класса, структура
inline Account:: Account() { name = ; balance = 0.0; acct nmbr = 0; то фаза инициализации будет неявной. Еще до выполнения тела конструктора вызывается конструктор по умолчанию класса string, ассоциированный с членом name. Это означает, что присваивание name пустой строки излишне. Для объектов классов различие между инициализацией и присваиванием существенно. Член, являющийся объектом класса, всегда следует инициализировать с помощью списка, а не присваивать ему значение в теле конструктора. Более правильной является inline Account:: Account() : name( string() ) { balance = 0.0; acct nmbr = 0; следующая реализация конструктора по умолчанию класса Account: удалили ненужное присваивание name из тела конструктора. Явный же вызов конструктора по умолчанию string излишен. Ниже приведена эквивалентная, но более inline Account:: Account() { balance = 0.0; acct nmbr = 0; компактная версия: Однако м1 еще не ответили на вопрос об инициализации двух членов встроенных типов. Например, так ли существенно, где происходит инициализация balance: в списке инициализации или в теле конструктора? Инициализация и присваивание членам, не являющимся объектами классов, эквивалентны как с точки зрения результата, так и с точки зрения производительности (за двумя исключениями). Мы предпочитаем / / предпочтительна стиль инициазации inline Account:: Account() : balance( 0.0 ), acct nmbr( 0 ) использовать список: class ConstRef { public: ConstRef(int ii ); private: int i; const int ci; int &ri; ConstRef:: ConstRef( int ii ) { присваивание ii; правильно ci = ii; ошибка: нельзя присваивать константному члену ri = i; ошибка: ri не инициазирована компилятор выдаст ошибку: К началу выполнения тела конструктора инициализация всех константных членов и членов-ссылок должна быть завершена. Для этого нужно указать их в списке правильно: инициализируются константные члены и ссылки ConstRef:: ConstRef( int ii ) : ci( ii ), ri ( i ) инициализации. Правильная реализация предыдущего примера такова: { i = ii; } Каждый член должен встречаться в списке инициализации не более одного раза. Порядок инициализации определяется не порядком следования имен в списке, а порядком class Account { public: ... private: unsigned int acct nmbr; double balance; string name; объявления членов. Если дано следующее объявление членов класса Account: inline Account:: Account() : name( string() ), balance( 0.0 ), acct nmbr( 0 ) то порядок инициализации для такой реализации конструктора по умолчанию Два в1шеуномянут1х исключения - это константные члены и члены-ссылки независимо от тина. Для них всегда нужно использовать список инициализации, в противном случае inline Account:: Account( const char* name, double bal : name( name ), balance( bal acct nmr = get unie acct nmbr(); следующем конструкторе: порядок инициализации такой: balance, name, acct nmbr. Расхождение между порядком инициализации и порядком следования членов в соответствующем списке может приводить к трудным для обнаружения ошибкам, когда class X { int i; int j; public: видите проблему? X( int val ) : j( val ), i( j ) ... один член класса используется для инициализации другого: Кажется, что перед использованием для инициализации i член j уже инициализирован значением val, но на самом деле i инициализируется первым, для чего применяется еще неинициализированный член j. Мы рекомендуем помещать инициализацию одного предпочтительная идиома члена другим (если вы считаете это необходимым) в тело конструктора: X::X( int val ) : i( val ) { j = i; } Упражнение 14.12 Что неверно в следующих определениях конструкторов? Как бы вы исправили обнаруженные ошибки? будет следующим: acct nmbr, balance, name. Однако члены, указанные в списке (или в неявно инициализируемом члене-объекте класса), всегда инициализируются раньше, чем производится присваивание членам в теле конструктора. Например, в
|
© 2006 - 2024 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки. |