Материалы книги получены с http://www.itlibitum.ru/
Небезопасные типы в закрытых базовых классах
Вот это уже больше похоже на истину. Самый простой способ обеспечить безопасность типов - сделать ненадежный класс закрытым базовым классом безопасного шаблона.
class UnsafeNode { // ListNode из предыдущего примера
private:
UnsafeNode* next;
void* data;
public:
UnsafeNode(void* d, UnsafeNode* n);
virtual ~UnsafeNode();
UnsafeNode* Next();
void* Data();
};
template <class Type>
class SafeNode : private UnsafeNode {
public:
SafeNode(Type* d, SafeNode* n) : UnsafeNode(d, n) {}
virtual ~SafeNode() { delete (Type*)Data(); }
SafeNode* Next() { return (SafeNode*)UnsafeNode::Next(); }
Type* Data() { return (Type*)UnsafeNode::Data(); }
Мы добились чего хотели - базовый класс недоступен для клиентов производного шаблона. Приведенный пример демонстрирует еще один прием, связанный с пространствами имен C++. Нет необходимости создавать в производном классе новые имена для функций Next() и Data() только потому, что они отличаются типом возвращаемого значения; поскольку ни одна из этих функций не является виртуальной, производная версия скрывает базовую от клиентов. Некоторые компиляторы при попытке скрытия членов базовых классов укоризненно грозят пальцем, но для закрытого наследования это предупреждение абсолютно безобидно. После всех огорчений, доставляемых вам компилятором, бывает приятно отплатить ему той же монетой.
Один из недостатков закрытого наследования - необходимость дублирования всех функций базового класса, которые могут безопасно использоваться клиентами. Впрочем, это происходит не так уж часто и в любом случае не является слишком высокой ценой за дополнительную безопасность. Примером может послужить наша реализация функций Next() и Data(), за исключением того, что интерфейс идентичен интерфейсу закрытого базового класса.
Назад Содержание Далее
|