Так private
члены в базовом классе также находятся в унаследованном классе, но не доступны в нем, верно?
Действительно ли они находятся в памяти, выделенной унаследованному объекту?
Действительно ли они находятся в памяти, выделенной унаследованному объекту?
Да, они должны существовать. Закрытые члены являются частью деталей реализации базового класса. Без них, как правило, базовый класс не сможет функционировать (именно поэтому они существуют в первую очередь).
Сделав их закрытыми, просто позволяет базовому классу создать свою реализацию, какую бы она ни выбрала, не раскрывая это никому, включая подкласс.
Да. Например, вы можете использовать открытую функцию из базового класса, которая манипулирует частными данными, даже в экземпляре производного класса:
class Base {
int x;
public:
Base() : x(0) {}
void inc() { ++x; }
void show() { std::cout << x << "\n"; }
};
class Derived : public Base {
};
int main() {
Derived d;
d.show();
d.inc();
d.show();
}
При правильно работающем компиляторе это должно отображать:
0
1
…показывает, что данные в объекте Base присутствуют в объекте Derived, даже если они (напрямую) недоступны.
Конечно, практически в C ++ есть правило «как если бы» — если компилятор может определить, что он может каким-то образом генерировать правильное наблюдаемое поведение для программы, даже не включая частные части базового класса, тогда это бесплатно. Самый очевидный пример этого будет, если вы включите в базовый класс что-то (функцию-член или данные), которое просто никогда не использовалось на практике.
Да,
Когда создается объект производного класса, сначала создаются все его базовые классы.
Рассмотрим этот пример:
class Base
{
int x;
public:
Base(int px)
: x(px)
{
}
};
class Derived : public Base
{
int y;
public:
Derived(int px, int py)
: y(py), Base(px)
{
}
};
Этот пример компилируется и работает, и Base инициализируется (вызывается конструктор), прежде чем вы достигнете тела конструктора Derived.