Программирование >>  Полиморфизм без виртуальных функций в с++ 

1 ... 133 134 135 [ 136 ] 137 138 139 ... 144


#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; старый способ: объявление доступа



1 ... 133 134 135 [ 136 ] 137 138 139 ... 144

© 2006 - 2024 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки.
Яндекс.Метрика