Наследование в C ++ - PullRequest
       4

Наследование в C ++

1 голос
/ 22 сентября 2011

Я возился с наследованием в C ++ и хотел узнать, есть ли у кого-нибудь понимание того, как оно функционирует. Код ниже

#include <iostream>
using namespace std;

class AA {
 int aa;
 public:
 AA() {cout<<"AA born"<<endl;}
~AA(){cout<<"AA killed"<<endl;} 
virtual void print(){ cout<<"I am AA"<<endl;}
};

class BB : public AA{
 int bb;
 public:
 BB() {cout<<"BB born"<<endl;}
~BB() {cout<<"BB killed"<<endl;}
 void print() {cout<<"I am BB"<<endl;}
};

class CC: public BB{
 int cc;
 public:
 CC() {cout<<"CC born"<<endl;}
~CC(){cout<<"CC killed"<<endl;}
 void print() {cout<<"I am CC"<<endl;}
};


int main()
{
 AA a;
 BB b;
 CC c;
 a.print();
 b.print();
 c.print();     
 return 0;
}

так что я понимаю, что когда вы наследуете что-то, вы наследуете конструкторы и деструкторы. Поэтому, когда я делаю «BB b», он печатает «AA born». Так что вопрос у меня

  1. Является ли экземпляр AA созданным
  2. Если да, как это называется и как я могу ссылаться на него?
  3. Если нет, почему конструктор вызывается

Ответы [ 6 ]

2 голосов
/ 22 сентября 2011

Наследование реализует отношение "IS-A".Следовательно, каждый BB также является AA.

Вы можете увидеть это несколькими способами, проще всего продемонстрировать это:

BB b;
AA *aptr = &b;

Здесь на ваш BB экземпляр b указывает указатель, который думает толькосамо по себе, как указание на AA.Если BB не унаследовал от AA, тогда это было бы недопустимо.

Интересно то, что когда вы звоните:

aptr->print();

Он все равно печатаетBB ", несмотря на то, что используемый вами указатель имеет тип AA *.Это происходит потому, что метод print() является virtual (т.е. полиморфным), и вы используете указатель.(То же самое может произойти и со ссылкой, но тип должен быть одним из тех, чтобы это поведение происходило)

1 голос
/ 22 сентября 2011

BB является экземпляром AA. Вам не нужно обращаться к чему-то особенному, потому что у вас уже есть этот тип.

Когда BB наследует от AA, вот как это построено.

  1. Звоните AA Конструктор
  2. Инициализация полей членов
  3. Звоните BB Конструктор

Когда происходит разрушение, это происходит в обратном порядке.

  1. Звоните BB Деструктор
  2. Уничтожить поля членов (специфично для BB)
  3. Звоните AA Деструктор

О, и у вас есть хотя бы одна виртуальная функция внутри AA. Это означает, что вам нужно сделать виртуальный деструктор AA (или произойдут плохие вещи).

1 голос
/ 22 сентября 2011
  1. Является ли экземпляр A созданным

Вроде. Код BB b; выделит экземпляр BB. Часть этого объекта - AA.

  1. Если да, как это называется и как я могу ссылаться на него?

При условии объявления переменной BB b; ваш экземпляр части BB AA называется b. Если вы хотите вызывать определенные методы в AA, которые скрыты методами BB, например, .print(), вам нужно вызывать их следующим образом:

BB b;
b.AA::print();
0 голосов
/ 26 августа 2016

Наследование в c ++ означает способность объектов в одном классе наследовать свойства другого класса, который реализует концепцию повторного использования. Это означает, что нет необходимости создавать новые методы и просто переопределять существующие, если это необходимо. Экономит много работы.

0 голосов
/ 22 сентября 2011

В объектно-ориентированных языках есть два основных способа создания объектов, которые наследуются от другого: конкатенация и делегирование.Первый является самым популярным, второй используется в основанных на прототипах языках.

Конкатенация означает, что когда B наследуется от A, в объекте есть две части: в первой части объекта (издлина равна размеру A), атрибуты (переменные-члены / поля в C ++) для A live.В другой части, существуют любые атрибуты, которые B добавляет к объекту.Конструкторы для каждого задействованного класса (A и B) выполняются таким образом, что все части (все атрибуты) инициализируются правильно.

Хотя объект управляется как единое целое, вы можете указать его указателем класса A.В этом случае указатель позволяет только видеть первую часть, часть, относящуюся к классу A (то есть его атрибутам), но не атрибуты из B, поскольку указатель может только видеть от начала к началу + размер класса A.

Скажем, класс A содержит целое число x:

class A {
public: int x;
};

, а B содержит целое число y:

class B: public A {
public: int y;
} obB;

Это означает, что объект класса B будет иметь длину 8 байтов (для 32 бит), длину x плюс длину y, а длина A составляет всего 4 байта, длину x.Указатель класса A на objB:

A * ptrA = &objB;

будет только видеть x,

cout << ptrA->x << endl;
cout << ptrA->y << endl; // ERROR

, а указатель на B:

B * ptrB = &objB;

будет иметь доступ к обоим x и y:

cout << ptrB->x << ',' << ptrB->y << endl;

Чтобы полностью это понять, вам нужно знать, что ptrB->y примерно переведено в *( ( (int *) ptrB ) + 1 ), ноэто другая история.

Надеюсь, это поможет.

0 голосов
/ 22 сентября 2011

Класс, производный от базового класса, содержит этот базовый класс как подкласс , поэтому экземпляр производного класса содержит базовый подобъект .

Подобъект строится первым. Конструктор, который для этого используется, определяется вами: если вы ничего не говорите, используется конструктор по умолчанию; в противном случае вызывается конструктор, указанный вами в базовом списке инициализатора. Пример:

struct Base
{
  Base() { }             // default constructor
  Base(int, double) { }  // some other constructor
  char q; 
};

struct A : Base
{
};

struct B : Base
{
  B() : A(12, 1.5) { }
};

И A, и B содержат Base в качестве подкласса. Когда вы говорите A a;, вызывается конструктор подобъекта по умолчанию. Когда вы говорите B b, подобъекты вызывают другой конструктор, потому что вы так сказали.

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

Вы можете ссылаться на членов подобъекта, указав имя: a.Base::q или b.Base::q. Если имя однозначное, это то же самое, что и a.q и b.q. Однако, когда вы имеете дело с переопределенными или скрытыми функциями-членами (и, возможно, множественным виртуальным наследованием), возможность явно указать подобъект может быть полезной или даже необходимой.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...