Вход/Регистрация
Стандарты программирования на С++. 101 правило и рекомендация
вернуться

Александреску Андрей

Шрифт:

В С++ последовательность преобразований типов может включать не более одного пользовательского преобразования. Однако когда в эту последовательность добавляются встроенные преобразования, ситуация может оказаться предельно запутанной. Решение здесь простое и состоит в следующем.

• По умолчанию используйте explicit в конструкторах с одним аргументом (см. рекомендацию 54):

class Widget { // ...

 explicit Widget(unsigned int widgetizationFactor);

 explicit Widget(const char* name, const Widget* other = 0);

};

• Используйте для преобразований типов именованные функции, а не соответствующие операторы:

class String { // ...

 const char* as_char_pointer const; // в традициях c_str

};

См. также обсуждение копирующих конструкторов, объявленных как

explicit
, в рекомендации 54.

Примеры

Пример 1. Перегрузка. Пусть у нас есть, например,

Widget::Widget(unsigned int)
, который может быть вызван неявно, и функция
Display
, перегруженная для
Widget
и
double
. Рассмотрим следующий сюрприз при разрешении перегрузки:

void Display(double); // вывод double

void Display(const Widget&); // Вывод Widget

Display(5); // гм! Создание и вывод Widget

Пример 2. Работающие ошибки. Допустим, вы снабдили класс

String
оператором operator
const char*
:

class String {

 // ...

public:

 operator const char*; // Грустное решение...

};

В результате этого становятся компилируемыми масса глупостей и опечаток. Пусть

s1
и
s2
— объекты типа
String
. Все приведенные ниже строки компилируются:

int x = s1 - s2; // Неопределенное поведение

const char* р = s1 - 5; // Неопределенное поведение

р = s1 + '0'; // делает не то, что вы ожидаете

if (s1 == "0") { ... } // делает не то, что вы ожидаете

Именно по этой причине в стандартном классе

string
отсутствует
operator const char*
.

Исключения

При нечастом и осторожном использовании неявные преобразования типов могут сделать код более коротким и интуитивно более понятным. Стандартный класс

std::string
определяет неявный конструктор, который получает один аргумент типа
const char*
. Такое решение отлично работает, поскольку проектировщики класса приняли определенные меры предосторожности.

• Не имеется автоматического преобразования

std::string
в
const char*
; такое преобразование типов выполняются при помощи двух именованных функций —
c_str
и
data
.

• Все операторы сравнений, определенные для

std::string
(например,
==
,
!=
,
<
), перегружены для сравнения
const char*
и
std::string
в любом порядке (см. рекомендацию 29). Это позволяет избежать создания скрытых временных переменных.

Но и при этом возникают определенные неприятности, связанные с перегрузкой функций.

void Display(int);

void Display(std::string);

Display(NULL); // вызов Display(int)

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

Display(std::string)
, код бы обладал неопределенным поведением, поскольку создание
std::string
из нулевого указателя некорректно, но конструктор этого класса не обязан проверять передаваемое ему значение на равенство нулю.)

Ссылки

[Dewhurst03] §36-37 • [Lakos96] §9.3.1 • [Meyers96] §5 • [Murray93] §2.4 • [Sutter00] §6, §20, §39

41. Делайте данные-члены закрытыми (кроме случая агрегатов в стиле структур С)

Резюме

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

  • Читать дальше
  • 1
  • ...
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • ...

Ебукер (ebooker) – онлайн-библиотека на русском языке. Книги доступны онлайн, без утомительной регистрации. Огромный выбор и удобный дизайн, позволяющий читать без проблем. Добавляйте сайт в закладки! Все произведения загружаются пользователями: если считаете, что ваши авторские права нарушены – используйте форму обратной связи.

Полезные ссылки

  • Моя полка

Контакты

  • chitat.ebooker@gmail.com

Подпишитесь на рассылку: