Правила программирования на С и С++. Главы 7-8 - Используйте структуры только тогда, когда все данные открытые и нет функций-членов

ОГЛАВЛЕНИЕ

 

114. Используйте структуры только тогда, когда все данные открытые и нет функций-членов.

Это правило является вариантом принципа "если это похоже на С, то должно и действовать как С". Используйте структуры, только если вы делаете что-то в стиле С.

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

typedef struct tagSIZE // Существующее определение из заголовочного файла С

{

LONG cx;

LONG cy;

}

SIZE;

class CSize : public SIZE // Определение в файле С++

{

// ...

}

Я видел определения классов, подобные следующему, где требуется доступ к полям cx и cy базового класса через указатель производного класса для того, чтобы определить соответствующее им значение третьей координаты - высоты. Например: CSize some_size;

some_size.cy; // тьфу!

Вы должны иметь возможность написать: some_size.height();

У предшествующего кода есть другая, более трудно уловимая проблема. Наследование от существующей структуры С часто выполняется программистом, который верит, что сможет передать объект С++ в существующую функцию С. То есть программист полагает, что раз наследование фактически добавляет поля к базовому классу, то производный класс в буквальном смысле будет расположен точно так же, как и базовый класс, но с присоединением нескольких дополнительных полей. Однако, это может и не быть правдой. Если производный класс добавляет, например, виртуальную функцию, то в базовый класс может быть добавлен указатель на таблицу виртуальных функций. Аналогично, если производный класс использует множественное наследование одновременно от структуры С и чего-то еще, то нет никакой гарантии, что структура С будет на верху.