Другие ответы объясняют причину, по которой ваш B
объект не получает доступ к защищенным частям A
в вашем примере, даже если B
'is-a' A
. Конечно, самый простой способ решить эту проблему - сделать части A you want access to
общедоступными или использовать общедоступные методы доступа.
Однако вы можете решить, что это неуместно (или вы не можете контролировать определение A
). Вот несколько советов, которые помогут вам обойти эту проблему в порядке возрастания степени нарушения контроля доступа A
. Обратите внимание, что все эти обходные приемы предполагают, что class A
является копируемым.
В первом случае вы просто используете конструктор копирования для A
, чтобы установить начальное состояние для этой части объекта B
, а затем исправите его:
class B1 : public A
{
public:
B1() : A(), z(0) {}
B1(const A& item) : A(item), z(1) {
// fix up the A sub-object that was copy constructed
// not quite the way we wanted
x = y;
y = 0;
}
private:
int z;
};
Я нахожу это невероятно запутанным и, вероятно, очень подверженным ошибкам (при условии, что мы хотим, чтобы подобъект A
в объекте B
отличался от объекта A
, передаваемого в конструктор - необычная ситуация, но это то, что было дано в задаче). Однако тот факт, что это может быть сделано, дает некоторое оправдание для более подрывных примеров, которые следуют ...
В следующем примере создается временный объект B
, имеющий точную копию объекта A
, к которому мы хотим получить доступ. Затем мы можем использовать временный объект B
, чтобы добраться до защищенных предметов:
class B2 : public A
{
public:
B2() : A(), z(0) {}
B2(const A& item) : A(), z(1) {
// create a special-use B2 object that can get to the
// parts of the A object we want access to
B2 tmp( item, internal_use_only);
x = tmp.y; // OK since tmp is of type B
}
private:
int z;
// create a type that only B2 can use as a
// 'marker' to call a special constructor
// whose only purpose in life is to create
// a B object with an exact copy of another
// A sub-object in it
enum internal_use {
internal_use_only
};
B2( const A& item, internal_use marker) : A(item), z(0) {};
};
Я считаю, что это решение немного менее запутанно, чем первое, но оно все еще запутанно (на мой взгляд). Наличие ублюдочной версии объекта B только для того, чтобы добраться до нужных нам частей объекта A, странно.
Мы можем что-то с этим сделать, создав специальный прокси для A
объектов, который дает доступ, который мы хотим. Обратите внимание, что это «самый подрывный» обходной путь, потому что любой класс может сделать это, чтобы добраться до защищенных частей A
, даже если они не являются подклассами A
сами по себе. В случае класса B
существует некоторая законность доступа к защищенным частям объектов A
, поскольку B
is-a A
, и, как мы уже видели, есть обходные пути, которые позволяют нам получить доступ, использующий только права, которые class B
уже имеет, поэтому я считаю, что это более чистая версия этих обходных путей в случае class B
.
class B3 : public A
{
public:
B3() : A(), z(0) {}
B3(const A& item) : A(), z(1) {
// a special proxy for A objects that lets us
// get to the parts of A we're interested in
A_proxy tmp( item);
x = tmp.get_y();
}
private:
int z;
class A_proxy : public A
{
public:
A_proxy( const A& other) : A(other) {};
int get_x() {return x;};
int get_y() {return y;};
};
};