if (obj.isbn() == Primer_5th_ed.isbn()) //
Проблема в том, что, несмотря на намерение объявить инициализированный значением по умолчанию объект obj, фактически была объявлена функция без параметров, возвращающая объект типа Sales_data.
Чтобы правильно определить объект, использующий стандартный конструктор для инициализации, следует убрать пустые круглые скобки:
//
Sales_data obj;
Sales_data obj(); //
Sales_data obj2; //
Упражнение 7.43. Предположим, имеется класс NoDefault, у которого есть конструктор, получающий параметр типа int, но нет стандартного конструктора. Определите класс С, у которого есть переменная-член типа NoDefault. Определите стандартный конструктор для класса С.
Упражнение 7.44. Допустимо ли следующее объявление? Если нет, то почему?
vector
Упражнение 7.45. Определите вектор, содержащий объекты типа С из предыдущего упражнения?
Упражнение 7.46. Которое из следующих утверждений, если таковое имеется, ложно? Почему?
(a) Класс должен предоставить по крайней мере один конструктор.
(b) Стандартный конструктор — это конструктор с пустым списком параметров.
(c) Если для класса не нужно никаких значений по умолчанию, то класс не должен предоставлять стандартный конструктор.
(d) Если класс не определяет стандартный конструктор, компилятор сам создает конструктор, который инициализирует каждую переменную-член значением по умолчанию соответствующего типа.
Как упоминалось в разделе 4.11, язык С++ автоматически осуществляет преобразование некоторых встроенных типов. Обращалось также внимание на то, что классы тоже могут определять неявные преобразования. Каждый конструктор, который может быть вызван с одним аргументом, определяет неявное преобразование в тип класса. Такие конструкторы иногда упоминают как
Конструкторы класса Sales_data, получающие строку и объект класса istream, оба определяют неявные преобразования из этих типов в тип Sales_data. Таким образом, можно использовать тип string или istream там, где ожидается объект типа Sales_data:
string null_book = "9-999-99999-9";
//
//
item.combine(null_book);
Здесь происходит вызов функции-члена combine() класса Sales_data со строковым аргументом. Этот вызов совершенно корректен; компилятор автоматически создаст объект класса Sales_data из данной строки. Этот вновь созданный (временный) объект класса Sales_data передается функции combine(). Поскольку параметр функции combine() является ссылкой на константу, этому параметру можно передать временный объект.
В разделе 4.11.2 обращалось внимание на то, что компилятор автоматически применит только одно преобразование типов класса. Например, следующий код ошибочен, поскольку он неявно использует два преобразования:
//
//
//
item.combine("9-999-99999-9");
Если данный вызов необходим, это можно сделать при явном преобразовании символьной строки в объект класса string или в объект класса Sales_data:
//
//
item.combine(string("9-999-99999-9"));
//