Категории
Самые читаемые
RUSBOOK.SU » Компьютеры и Интернет » Программирование » Справочное руководство по C++ - Бьярн Страустрап

Справочное руководство по C++ - Бьярн Страустрап

Читать онлайн Справочное руководство по C++ - Бьярн Страустрап

Шрифт:

-
+

Интервал:

-
+

Закладка:

Сделать
1 ... 16 17 18 19 20 21 22 23 24 ... 41
Перейти на страницу:

};

typedef enclose::inner ei;

int ei::x = 1;

void enclose::inner::f(int i) {/*… */}

Подобно функции-члену дружественная функция, определенная в данном классе, находится в области видимости этого класса. Она подчиняется тем же правилам связывания имен, что и функции-члены (они указаны выше и в §R.10.4), и не имеет так же как они особых прав доступа к членам объемлющего класса и к локальным переменным функций этого класса (§R.11).

R.9.8 Описания локальных классов

Класс можно описать в определении функции, такой класс называется локальным. Имя локального класса считается локальным в объемлющей области видимости, а областью видимости локального класса является объемлющая область видимости. В описаниях локального класса из объемлющей области видимости можно использовать только имена типов, статических переменных, внешних переменных и функций, а также элементы перечисления. Приведем пример:

int x;

void f()

{

 static int s;

 int x;

 extern int g();

 struct local {

  int h() { return x; } // ошибка: `x' автоматическая

  int j() { return s; } // нормально

  int k() { return ::x; } // нормально

  int l() { return g(); } // нормально

 }

}

Объемлющая функция не имеет особых прав доступа к членам локального класса, она подчиняется обычным правилам доступа (§R.11). Функцию-член локального класса следует определять в определении этого класса. Локальный класс не может иметь статических членов, представляющих данные.

R.9.9 Имена локальных типов

Имена типов подчиняются точно таким же правилам областей видимости, как и другие имена. В частности, имена типов, определенные в описании класса, нельзя использовать вне этого класса без уточнения, например:

class X {

public:

 typedef int I;

 class Y {/*… */}

 I a;

};

I b; // ошибка

Y c; // ошибка

X::Y d; // ошибка

Следующее положение ограничивает зависимость от контекста правил описания членов класса, а так же правила переноса тела функций, являющихся подстановками. После использования в описании класса имя константы, имя-класса или имя-typedef не может переопределяться в описании этого класса. Имя, не являющееся именем-класса или именем-typedef не может быть определено в описании класса как имя-класса или имя-typedef, если оно уже использовалось иначе в описании этого класса. Рассмотрим пример:

typedef int c;

enum { i = 1 };

class X {

 char v[i];

 int f() { return sizeof(c); }

 char c; // ошибка: имя typedef

  // переопределяется после использования

 enum { i = 2 }; // ошибка: `i' переопределяется после

  // использования в задании типа `char[i]'

};

typedef char* T;

struct Y {

 T a;

 typedef long T; // ошибка: имя T уже использовано

 T b;

};

R.10 Производные классы

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

спец-базовых:

 : список-базовых

список-базовых:

 спецификация-базовых

 список-базовых , спецификация-базовых

спецификация-базовых:

 полное-имя-класса

 virtual спецификация-доступа opt полное-имя-класса

 спецификация-доступа virtual opt полное-имя-класса

спецификация-доступа:

 private

 protected

 public

Конструкция имя-класса в спецификации-базовых должна обозначать ранее описанный класс (§R.9), который называется базовым по отношению к определяемому классу. Говорят, что класс является производным от своих базовых классов. Назначение конструкции спецификация-доступа объясняется в §R.11. К членам базового класса, если только они не переопределены в производном классе, можно обращаться так, как будто они являются членами производного класса. Говорят, что производный класс наследует члены базового класса. С помощью операции разрешения области видимости :: (§R.5.1) к члену базового класса можно обращаться явно. Такое обращение возможно и в том случае, когда имя члена базового класса переопределено в производном классе. Производный класс сам может выступать как базовый при контроле доступа, см. §R.11.2. Указатель на производный класс может неявно преобразовываться в указатель на однозначно определенный и доступный базовый класс (§R.4.6). Ссылка на производный класс может неявно преобразовываться в ссылку на однозначно определенный и доступный базовый класс (§R.4.7).

Рассмотрим пример:

class base {

 public:

 int a, b;

};

class derived: public base {

 public:

 int b, c;

};

void f()

{

 derived d;

 d.a = 1;

 d.base::b = 2;

 d.b = 3;

 d.c = 4;

 base* bp = &d; // стандартное преобразование derived* в base*

}

Здесь присваиваются значения четырем членам d, а bp настраивается на d.

Класс называется прямым базовым, если он находится в списке-базовых, и косвенным базовым, если сам не являясь прямым базовым, он служит базовым для одного из классов списка-базовых.

Отметим, что в обозначении имя-класса :: имя конструкция, имя может быть именем члена косвенного базового класса. Такое обозначение просто указывает класс, в котором следует начинать поиск этого имени.

Приведем пример:

class A { public: void f(); }

class B: public A {};

class C: public B { public: void f(); }

void C::f()

{

 f(); // вызов f() из C

 A::f(); // вызов f() из A

 B::f(); // вызов f() из A

}

Здесь дважды вызывается A::f(), поскольку это единственная функция f() в классе B.

Инициализация объектов, представляющих базовые классы, задается в конструкторах, см. §R.12.6.2.

R.10.1 Множественные базовые классы

Класс может быть производным по отношению к любому числу базовых классов. Приведем пример:

class A {/*… */};

class B {/*… */};

class C {/*… */};

class D: public A, public B, public C {/*… */};

Использование более, чем одного прямого базового класса называется множественным наследованием.

Порядок наследования не важен, если не учитывать вопросов, связанных со стандартной инициализацией с помощью конструктора (§R.12.1), уничтожением (§R.12.4) и размещением в памяти ($$r.5.4, §R.9.2, §R.11.1). Порядок выделения памяти для базовых классов определяется реализацией.

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

class B {/*… */};

class D: public B, public B {/*… */}; // недопустимо

class L {/*… */};

class A: public L {/*… */};

class B: public L {/*… */};

class C: public A, public B {/*… */}; // нормально

Здесь объект класса C будет иметь два вложенных объекта класса L.

К спецификации базового класса можно добавить служебное слово virtual. Отдельный объект виртуального базового класса V разделяется между всеми базовыми классами, которые указали V при задании своих базовых классов. Приведем пример:

class V {/*… */};

class A: virtual public V {/*… */};

class B: virtual public V {/*… */};

class C: public A, public B {/*… */};

Здесь объект класса C будет иметь только один вложенный объект класса V.

Класс может содержать виртуальные и невиртуальные базовые классы одного типа, например:

class B {/*… */};

class X: virtual public B {/*… */};

class Y: virtual public B {/*… */};

class Z: public B {/*… */};

class AA: public X, public Y, public Z {/*… */};

Здесь объект класса AA будет иметь два вложенных объекта класса B: из класса Z и виртуальный, разделяемый между классами X и Y.

R.10.1.1 Неоднозначности

Доступ к базовому классу должен быть задан однозначно. Доступ к члену базового класса считается неоднозначным, если выражение, используемое для доступа, задает более одной функции, объекта, типа или элемента перечисления. Проверка на однозначность происходит до проверки возможности доступа (§R.11). Приведем пример:

class A {

public:

 int a;

 int (*b)();

 int f();

 int f(int);

 int g();

};

class B {

 int a;

 int b();

public:

 int f();

 int g();

 int h();

1 ... 16 17 18 19 20 21 22 23 24 ... 41
Перейти на страницу:
На этой странице вы можете бесплатно скачать Справочное руководство по C++ - Бьярн Страустрап торрент бесплатно.
Комментарии
Открыть боковую панель
Комментарии
Сергій
Сергій 25.01.2024 - 17:17
"Убийство миссис Спэнлоу" от Агаты Кристи – это великолепный детектив, который завораживает с первой страницы и держит в напряжении до последнего момента. Кристи, как всегда, мастерски строит