Язык программирования C++ для профессионалов



           

Компоненты - часть 2


// не используйте специфику реализации compX, // если только вы не разработчик compX: extern void compX_f(T2*, const char*); extern T3 compX_v; // ...

Такие имена как compX_f и compX_v вряд ли могут привести к коллизии, а на тот довод, что пользователь может быть злоумышленником и использовать эти имена прямо, можно ответить, что пользователь в любом случае может оказаться злоумышленником, и что языковые механизмы защиты предохраняют от несчастного случая, а не от злого умысла. Преимущество этого решения в том, что оно применимо всегда и хорошо известно. В то же время оно некрасиво, ненадежно и усложняет ввод текста.

Второе решение более надежно, но менее универсально:

// специфика реализации compX: static void compX_f(T2* a1, const char *a2) { /* ... */ } static T3 compX_v; // ...

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

Третье решение можно рассматривать как формализацию и обобщение первых двух:

class compX_details { // специфика реализации compX public: static void f(T2*, const char*); static T3 v; // ... };

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

В компоненте конечно может быть много классов, не предназначенных для общего пользования. Если их имена тоже рассчитаны только на локальное использование, то их также можно "спрятать" внутри классов, содержащих специфику реализации:

class compX_details { // специфика реализации compX. public: // ... class widget { // ... }; // ... };

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




Содержание  Назад  Вперед