|
Программирование >> Полиморфизм без виртуальных функций в с++
#include <stdio.h> extern int g(); моя функция ... можно переписать, не меняя порядок объявлений: мой заголовочный файл: namespace Mine { void f() ; моя функция ... #include <stdio.h> namespace Mine { int g(); моя функция . . . Многие, в том числе и я, предпочитают использовать несколько маленьких пространств имен, вместо того чтобы помещать крупные фрагменты кода в одно пространство. Подобный стиль можно навязать, если требовать, чтобы все члены входили в единственное объявление пространства имен точно так же, как в одном объявлении были бы объявлены все члены класса. Но я не видел смысла приносить многие мелкие удобства, которые сопутствуют открытым пространства.м имен, в жертву ограничительной системе только для того, чтобы угодить преобладающим на данный момент вкусам. 17.5. Классы и пространства имен Не думаю, что однажды поступившее предложение сделать пространство и.мен разновидностью класса - хорошая мысль, поскольку многие возможности, предоставляемые классами, лишь поддерживают концепцию определенного пользователем типа данных. Например, средства создания объектов и манипулирования ими имеют мало общего с областя.ми действия. Противоположная точка зрения - класс является частным случаем пространства имен - почти не вызывает сомнений. Класс действительно есть пространство имен в том смысле, что все операции, поддерживаемые для пространств и.меп, применимы с той же семантикой и к классам, если только конкретная операция для классов явно не запрещена. Это позволяет достичь простоты и единства языка, одновременно сводя к мини.муму затраты на реализацию. Такой взгляд подтверждается легкостью, с которой пространства имен вошли в С-ы-, и тем, как естественно с их помощью решаются давно стоящие и, казалось бы, не связанные между собой проблемы. 17.5.1. Производные классы Рассмотрим известную проблему, связанную с тем, что член производного класса скрывает член базового класса с тем же именем: class В { public: f(char); class D : public В { public: f(int); скрывает f(char) void f(D& d) { d.f(c); вызывается D::f(int) Разумеется, появление пространств имен не изменяет семантики таких примеров. Но возможна новая интерпретация: поскольку D - это класс, его область действия представляет собой пространство имен. Пространство имен D вложено в В, поэтому D: : f (int) скрывает В: : f (char). Следовательно, вызывается D: : f (int}. Если такое разрешение имени вас не устраивает, можете воспользоваться using-объявлением, чтобы включить f () из В в область действия: class В { public: f(char); class D : public В { public: f(int); ввести B::f в D, разрешив перегрузку using В::f; void f(D& d) { d.f(c); вызывается D::f(char) Как обычно, имена из двух базовых классов, которым множественно наследует производный класс, могут приводить к неоднозначности (независимо от того, что обозначают имена): struct А { void f(int); }; struct В { void f(double); }; struct С : A, В { void g() { f(l); ошибка: A::f(int) или В::f(double) f(l.O); ошибка: A::f(int) или В::f(double) Но теперь для разрешения таких неоднозначностей мы можем добавить пару using-объявлений, чтобы ввести А: : f и В: : f в область действия С: struct с : А, в { using А::f; using В::f; void g() { f(l); A::f(l) f(l.O); B::f(1.0) Явный механизм такого рода неоднократно предлагался на протяжении нескольких лет. Я помню, как мы обсуждали эту тему с Джонатаном Шопиро во время работы над версией 2.0, но отказались от ее реализации, поскольку механизм казался слишком специализированным и узким. С другой стороны, using-объявления - обший механизм, который по счастливой случайности решил и эту проблему. 17.5.2. Использование базовых классов Во избежание путаницы using-объявление, являющееся членом класса, должно именовать член базового (непосредственного или косвенного) класса. Чтобы не было проблем с правилом доминирования (см. раздел 12.3.1), использование using-директив в качестве членов классов запрещено. struct D : public А { using namespace А; ошибка: using-директива в качестве члена using ::f; ошибка: ::f - не член базового класса Using-объявление, именующее член базового класса, играет важную роль для повышения единообразия доступа: class В { public: f (char) ; class D : private В { public: using B::f; Это более общий и понятный способ добиться того же, что раньше делалось с помошью объявлений доступа (см. раздел 2.10): class D : private В { public: В::f; старый способ: объявление доступа
|
© 2006 - 2024 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки. |