Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
C++ для начинающих (Стенли Липпман) 3-е хххх.pdf
Скачиваний:
85
Добавлен:
30.05.2015
Размер:
5.92 Mб
Скачать

С++ для начинающих

665

// в каком-то заголовочном файле

 

extern void print( const Account &acct );

 

// ...

 

int main()

{

//преобразует строку "oops" в объект класса Account

//с помощью конструктора Account::Account( "oops", 0.0 ) print( "oops" );

//...

}

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

компилятором для трансформации литеральной строки в объект класса Account при вызове print(), хотя в данной ситуации такое преобразование не нужно.

Непреднамеренные неявные преобразования классов, например трансформация "oops" в объект класса Account, оказались источником трудно обнаруживаемых ошибок. Поэтому в стандарт C++ было добавлено ключевое слово explicit, говорящее

class Account { public:

explicit Account( const char*, double=0.0 );

компилятору, что такие преобразования не нужны:

};

Данный модификатор применим только к конструктору. (Операторы преобразования и слово explicit обсуждаются в разделе 15.9.2.)

14.2.1. Конструктор по умолчанию

Конструктором по умолчанию называется конструктор, который можно вызывать, не задавая аргументов. Это не значит, что такой конструктор не может принимать аргументов; просто с каждым его формальным параметром ассоциировано значение по

// все это конструкторы по умолчанию

Account::Account() { ... } iStack::iStack( int size = 0 ) { ... }

умолчанию:

Complex::Complex(double re=0.0, double im=0.0) { ... }

Когда мы пишем:

С++ для начинающих

666

int main()

{

Account acct; // ...

}

то компилятор сначала проверяет, определен ли для класса Account конструктор по умолчанию. Возникает одна из следующих ситуаций:

1.Такой конструктор определен. Тогда он применяется к acct.

2.Конструктор определен, но не является открытым. В данном случае определение acct помечается компилятором как ошибка: у функции main() нет прав доступа.

3.Конструктор по умолчанию не определен, но есть один или несколько конструкторов, требующих задания аргументов. Определение acct помечается как ошибка: слишком мало аргументов у конструктора.

4.Нет ни конструктора по умолчанию, ни какого-либо другого. Определение считается корректным, acct не инициализируется, конструктор не вызывается.

Пункты 1 и 3 должны быть уже достаточно понятны (если это не так, перечитайте данную главу) Посмотрим более внимательно на пункты 2 и 4.

Допустим, что все члены класса Account объявлены открытыми и не объявлено никакого

class Account {

 

public:

*_name;

char

unsigned int

_acct_nmbr;

double

_balance;

конструктора:

};

В таком случае при определении объекта класса Account специальной инициализации не производится. Начальные значения всех трех членов зависят только от контекста, в котором встретилось определение. Например, для статических объектов гарантируется, что все их члены будут обнулены (как и для объектов, не являющихся экземплярами

//статический класс хранения

//вся ассоциированная с объектом память обнуляется

Account global_scope_acct; static Account file_scope_acct;

Account foo()

{

static Account local_static_acct; // ...

классов):

}