Так что private
членов в базовом классе также находятся в унаследованном классе, но недоступны в нем, правильно?
Действительно ли они находятся в памяти, выделенной для унаследованного объекта?
Почему частные члены наследуются?
ответ
Действительно ли они находятся в памяти, выделенной для унаследованного объекта?
Да, они должны существовать. Частные члены являются частью детализации реализации базового класса. Без них, в общем, базовый класс не сможет функционировать (вот почему они существуют в первую очередь).
Создание частного доступа позволяет базовому классу создавать его реализацию, однако он выбирает, не подвергая его никому, включая подкласс.
В дополнение к этому хороший ответ, я бы сказал, что в основном, когда у вас есть базовый класс MyBase, например, он наследуется каким-то классом MyDerived (независимо от того, как - public, private или protected), и когда вы создаете объект типа MyDerived, в макете объекта в памяти у вас на самом деле будет объект типа MyBase. Так просто сказал: каждый объект типа MyDerived будет иметь объект типа MyBase внутри него. – BlackCat
@BlackCat - Re * Так просто сказал: каждый объект типа MyDerived будет иметь объект типа MyBase внутри него. * Наследование диаманта. Предположим, что B и C наследуют фактически от A, D, наследуемых от B и C. По крайней мере один из объектов B и C, встроенных внутри экземпляра класса D, не будет содержать объект A внутри. –
@David: оба из B и C будут иметь указатель на общий (общий) объект базового класса A. И хотя они не обязательно имеют объект класса А внутри, они ведут себя так, как они. – Tomek
Да. Просто, например, вы можете использовать публичную функцию базового класса, который манипулирует личные данные, даже в случае производного класса:
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
... показывая, что данные в базовом объекте присутствуют в объекте Derived, хотя он недоступен (напрямую).
Конечно, в C++ существует правило «как есть» - если компилятор может определить, что он может каким-то образом создать правильное наблюдаемое поведение для программы, даже без включения частной части (-ов) базовый класс, тогда он свободен. Наиболее очевидным примером этого может быть, если вы включили что-то (функция-член или данные) в базовый класс, который просто никогда не использовался на практике.
Что делать, если вы компилируете в дистрибутивную DLL, как вы можете узнать, не использует ли какая-либо конкретная функция-член? – TemplateRex
@TemplateRex: Скорее всего, это невозможно, поэтому при таких обстоятельствах у него, скорее всего, нет возможности его упустить. –
Я думаю, что фундаментальная проблема когда-то производного класса состоит в том, что его можно унаследовать снова, а потенциальные дети - это открытый набор. Поэтому, если «Derived» не помечен как «final», я не думаю, что компилятор может применить правило as-if к его классу-макету. Кроме того, набор будущих абонентов также является открытым набором. – TemplateRex
Да они,
Когда объект производного класса строится все его базовых классов первых строится так же.
Рассмотрим следующий пример:
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)
{
}
};
Этот пример компилируется и работает и база инициализируется (вызывается конструктор), прежде чем достичь тело Derived конструктора.
Наследование является отношением 'is-a', поэтому да, вся память, которую требует базовый класс, требуется в подклассе. – clcto