2013-10-15 2 views
4

Так что private членов в базовом классе также находятся в унаследованном классе, но недоступны в нем, правильно?
Действительно ли они находятся в памяти, выделенной для унаследованного объекта?
Почему частные члены наследуются?

+2

Наследование является отношением 'is-a', поэтому да, вся память, которую требует базовый класс, требуется в подклассе. – clcto

ответ

7

Действительно ли они находятся в памяти, выделенной для унаследованного объекта?

Да, они должны существовать. Частные члены являются частью детализации реализации базового класса. Без них, в общем, базовый класс не сможет функционировать (вот почему они существуют в первую очередь).

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

+1

В дополнение к этому хороший ответ, я бы сказал, что в основном, когда у вас есть базовый класс MyBase, например, он наследуется каким-то классом MyDerived (независимо от того, как - public, private или protected), и когда вы создаете объект типа MyDerived, в макете объекта в памяти у вас на самом деле будет объект типа MyBase. Так просто сказал: каждый объект типа MyDerived будет иметь объект типа MyBase внутри него. – BlackCat

+0

@BlackCat - Re * Так просто сказал: каждый объект типа MyDerived будет иметь объект типа MyBase внутри него. * Наследование диаманта. Предположим, что B и C наследуют фактически от A, D, наследуемых от B и C. По крайней мере один из объектов B и C, встроенных внутри экземпляра класса D, не будет содержать объект A внутри. –

+0

@David: оба из B и C будут иметь указатель на общий (общий) объект базового класса A. И хотя они не обязательно имеют объект класса А внутри, они ведут себя так, как они. – Tomek

6

Да. Просто, например, вы можете использовать публичную функцию базового класса, который манипулирует личные данные, даже в случае производного класса:

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++ существует правило «как есть» - если компилятор может определить, что он может каким-то образом создать правильное наблюдаемое поведение для программы, даже без включения частной части (-ов) базовый класс, тогда он свободен. Наиболее очевидным примером этого может быть, если вы включили что-то (функция-член или данные) в базовый класс, который просто никогда не использовался на практике.

+0

Что делать, если вы компилируете в дистрибутивную DLL, как вы можете узнать, не использует ли какая-либо конкретная функция-член? – TemplateRex

+0

@TemplateRex: Скорее всего, это невозможно, поэтому при таких обстоятельствах у него, скорее всего, нет возможности его упустить. –

+0

Я думаю, что фундаментальная проблема когда-то производного класса состоит в том, что его можно унаследовать снова, а потенциальные дети - это открытый набор. Поэтому, если «Derived» не помечен как «final», я не думаю, что компилятор может применить правило as-if к его классу-макету. Кроме того, набор будущих абонентов также является открытым набором. – TemplateRex

2

Да они,

Когда объект производного класса строится все его базовых классов первых строится так же.

Рассмотрим следующий пример:

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 конструктора.

 Смежные вопросы

  • Нет связанных вопросов^_^