Бьярн Страустрап - Справочное руководство по C++
- Название:Справочное руководство по C++
- Автор:
- Жанр:
- Издательство:неизвестно
- Год:неизвестен
- ISBN:нет данных
- Рейтинг:
- Избранное:Добавить в избранное
-
Отзывы:
-
Ваша оценка:
Бьярн Страустрап - Справочное руководство по C++ краткое содержание
Справочное руководство по C++ - читать онлайн бесплатно полную версию (весь текст целиком)
Интервал:
Закладка:
class B {/*… */};
class D1: private B {/*… */};
class D2: public B {/*… */};
class D3: B {/*… */}; // `B' частный по определению
struct D4: public B {/*… */};
struct D5: private B {/*… */};
struct D6: B {/*… */}; // `B' частный по определению
Здесь класс является общим (public) базовым классом для D2, D4 и D6 и частным (private) базовым классом для D1, D2 и D5.
Описание базового класса как private не влияет на доступ к статическим членам базового класса. Однако, если при обращении к статическому члену используется объект или указатель, который нужно преобразовывать, то действуют обычные правила преобразования указателей.
В функциях-членах или друзьях класса X можно X* неявно преобразовывать в указатель на частный класс, являющийся непосредственно базовым по отношению к X.
R.11.3 Описания доступа
Используя уточненное имя, можно установить доступ к члену базового класса в части public или protected описания производного класса. Это называется описанием доступа.
Приведем пример:
class B {
int a;
public:
int b, c;
int bf();
};
class D: private B {
int d;
public:
B::c; // adjust access to `B::c'
int e;
int df();
};
int ef(D&);
Во внешней функции ef можно использовать только имена c, e, и df. Поскольку функция df член класса D, в ней можно использовать имена b, c, bf, d, e и df, но не a. Функция bf - член класса B и в ней можно использовать члены a, b, c и bf.
Описания доступа не следует использовать для ограничения доступа к члену, доступному в базовом классе, также как не следует использовать его для обеспечения доступа к члену, который недоступен в базовом классе, например:
class B {
public:
int a;
private:
int b;
protected:
int c;
};
class D: private B {
public:
B::a; // описать `a' как общий член D
B::b; // ошибка: попытка расширить доступ,
// `b' не может быть общим членом D
protected:
B::c; // описать `c' как защищенный член D
B::a; // ошибка: попытка сузить доступ,
// `a' не может быть защищенным членом D
};
Описание доступа для имени перегруженной функции устанавливает доступ в базовом классе ко всем функциям с этим именем, например:
class X {
public:
f();
f(int);
};
class Y: private X {
public:
X::f; // makes X::f() and X::f(int) public in Y
};
Нельзя в производном классе установить доступ к члену базового класса, если в производном классе определен член с этим же именем, например:
class X {
public:
void f();
};
class Y: private X {
public:
void f(int);
X::f; // ошибка: два описания f
};
R.11.4 Друзья
Другом класса называется функция, которая не является членом класса, но в которой можно использовать частные и защищенные члены этого класса. Имя друга не принадлежит области видимости класса, и дружественная функция не вызывается с помощью операций доступа к членам (§R.5.2.4), если только она не является членом другого класса. Следующий пример показывает различие между членами и друзьями:
class X {
int a;
friend void friend_set(X*, int);
public:
void member_set(int);
};
void friend_set(X* p, int i) {p-›a = i;}
void X::member_set(int i) {a = i;}
void f()
{
X obj;
friend_set(&obj,10);
obj.member_set(10);
}
Если в описании friend использовано имя перегруженной функции или операции, только функция, однозначно определяемая типами формальных параметров, становится другом. Функция-член класса X может быть другом класса Y, например:
class Y {
friend char* X::foo(int);
//…
};
Можно объявить все функции класса X друзьями класса Y с помощью спецификации-сложного-типа (§R.9.1):
class Y {
friend class X;
//…
};
Описание одного класса как друг другого класса дополнительно подразумевает, что частные и защищенные члены класса, предлагающего дружбу, могут использоваться в классе, получающем ее, например:
class X {
enum { a=100 };
friend class Y;
};
class Y {
int v[X::a]; // Y друг класса X
};
class Z {
int v[X::a]; // ошибка: X::a недоступно
};
Если класс или функция, объявленные как друзья, не были описаны, их имена попадают в ту же область видимости, что и имя класса, содержащего описание friend (§R.9.1).
Функция, появившаяся первый раз в описании friend, считается эквивалентной функции, описанной как extern (§R.3.3, §R.7.1.1).
Если функция-друг определена в описании класса, она считается функцией со спецификацией inline и к ней применимо правило переноса определения функции для функций-членов (§R.9.3.2). Функция-друг, определенная в описании класса, относится на лексическом уровне к области видимости этого класса. Для функции-друга, определенной вне класса, это не так.
На описание friend не влияет указание спецификаций-доступа (§R.9.2).
Понятие дружбы не является ни наследуемым, ни транзитивным.
Подтвердим это примером:
class A {
friend class B;
int a;
};
class B {
friend class C;
};
class C {
void f(A* p);
{
p-›a++; // ошибка: C не друг класса A, хотя
// является другом друга класса A
}
};
class D: public B {
void f(A* p)
{
p-›a++; // ошибка: D не друг класса A, хотя
// является производным друга класса A
}
};
R.11.5 Доступ к защищенным членам
Друг или функция-член производного класса имеет доступ к защищенному статическому члену базового класса. Друг или функция-член производного класса могут получить доступ к защищенному нестатическому члену одного из своих базовых классов только через указатель, ссылку или объект производного класса (или любого класса, являющегося производным по отношению к нему). Рассмотрим пример:
class B {
protected:
int i;
};
class D1: public B {
};
class D2: public B {
friend void fr(B*, D1*, D2*);
void mem(B*, D1*);
};
void fr(B* pb, D1* p1, D2* p2)
{
pb-›i = 1; // недопустимо
p1-›i = 2; // недопустимо
p2-›i = 3; // нормально (обращение через D2)
}
void D2::mem(B* pb, D1* p1)
{
pb-›i = 1; // недопустимо
p1-›i = 2; // недопустимо
i = 3; // нормально (обращение через this)
}
void g(B* pb, D1* p1, D2* p2)
{
pb-›i = 1; // недопустимо
p1-›i = 2; // недопустимо
p2-›i = 3; // недопустимо
}
R.11.6 Доступ к виртуальным функциям
Интервал:
Закладка: