В первом вызове конструктор Sales_data() используется непосредственно. Этот вызов создает временный объект класса Sales_data, используя конструктор Sales_data(), получающий строку. Во втором вызове используется оператор static_cast (см. раздел 4.11.3) для выполнения явного, а не неявного преобразования. В этом вызове оператор static_cast использует для создания временного объекта класса Sales_data конструктор с параметром типа istream.

Библиотечные классы с явными конструкторами

У некоторых библиотечных классов, включая уже использованные ранее, есть конструкторы с одним параметром.

• Конструктор класса string, получающий один параметр типа const char* (см. раздел 3.2.1), не является явным.

• Конструктор класса vector, получающий размер вектора (см. раздел 3.3.1), является явным.

Упражнения раздела 7.5.4

Упражнение 7.47. Объясните, должен ли быть явным конструктор Sales_data(), получающий строку. Каковы преимущества объявления конструктора явным? Каковы недостатки?

Упражнение 7.48. С учетом того, что конструктор Sales_data() не является явным, какие операции происходят во время следующих определений:

string null_isbn("9-999-99999-9");

Sales_data item1(null_isbn);

Sales_data item2("9-999-99999-9");

Что будет при явном конструкторе Sales_data()?

Упражнение 7.49. Объясните по каждому из следующих трех объявлений функции combine(), что происходит при вызове i.combine(s), где i — это объект класса Sales_data, a — строка:

(a) Sales_data &combine(Sales_data);

(b) Sales_data &combine(Sales_data&);

(c) Sales_data &combine(const Sales_data&) const;

Упражнение 7.50. Определите, должен ли какой-либо из конструкторов вашего класса Person быть явным.

Упражнение 7.51. Как, по вашему, почему вектор определяет свой конструктор с одним аргументом как явный, а строка нет?

<p><image l:href="#books.png"/>7.5.5. Агрегатные классы</p>

Агрегатный класс (aggregate class) предоставляет пользователям прямой доступ к своим членам и имеет специальный синтаксис инициализации. Класс считается агрегатным в следующем случае.

• Все его переменные-члены являются открытыми (public).

• Он не определяет конструкторы.

• У него нет никаких внутриклассовых инициализаторов (см. раздел 2.6.1).

• У него нет никаких базовых классов или виртуальных функций, связанных с классом средствами, которые рассматриваются в главе 15.

Например, следующий класс является агрегатным:

struct Data {

 int ival;

 string s;

};

Для инициализации переменных-членов агрегатного класса можно предоставить заключенный в фигурные скобки список инициализаторов для переменных-членов:

// val1.ival = 0; val1.s = string("Anna")

Data val1 = { 0, "Anna" };

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

// ошибка: нельзя использовать "Anna" для инициализации ival или 1024

// для инициализации s

Data val2 = { "Anna" , 1024 };

Как и при инициализации элементов массива (см. раздел 3.5.1), если в списке инициализаторов меньше элементов, чем переменных-членов класса, последние переменные-члены инициализируются значением по умолчанию. Список инициализаторов не должен содержать больше элементов, чем переменных-членов у класса.

Следует заметить, что у явной инициализации переменных-членов объекта класса есть три существенных недостатка.

• Она требует, чтобы все переменные-члены были открытыми.

• Налагает дополнительные обязанности по правильной инициализации каждой переменной-члена каждого объекта на пользователя класса (а не на его автора). Такая инициализация утомительна и часто приводит к ошибкам, поскольку достаточно просто забыть инициализатор или предоставить неподходящее значение.

• Если добавляется или удаляется переменная-член, придется изменить все случаи инициализации.

Упражнения раздела 7.5.5

Упражнение 7.52. На примере первой версии класса Sales_data из раздела 2.6.1 объясните следующую инициализацию. Найдите и исправьте возможные ошибки.

Sales_data item = {"978-0590353403", 25, 15.99};

<p><image l:href="#books.png"/>7.5.6. Литеральные классы</p>
Перейти на страницу:

Похожие книги