Инициализация наследования в основной функции в C ++

0

За последние несколько недель я изучаю и экспериментирую наследование и полиморфизм в C++.

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

например:

#include <iostream.h>

using namespace std;

class Base
{
public:
    Base(){ cout<<"Constructing Base";}

virtual ~Base(){ cout<<"Destroying Base";}
};

class Derive: public Base
{
    public:
    Derive(){ cout<<"Constructing Derive";}

    ~Derive(){ cout<<"Destroying Derive";}
};

void main()
{
    Base *basePtr = new Derive();

    delete basePtr;
 }

Вот мой вопрос:

Что на самом деле происходит, когда Base * basePtr = new Derive(); этот синтаксис называется? и каковы преимущества?

По моим сведениям, я понял, что он вызывает getive объект класса и сохраняет его в указателе на объект базового класса. Я прав? Если да, то почему мы храним его в базовом классе?

Чтобы устранить мои сомнения, я просмотрел схему памяти объектов класса и разборки, но это меня смущает больше.

Может ли кто-нибудь сказать мне, как понимать этот синтаксис?

  • 1
    Только одно слово: полиморфизм.
  • 0
    «Насколько я знаю, я понял, что он вызывает производный объект класса и сохраняет его в объекте базового класса». Нет, он сохраняет результат в указателе на объект базового класса. Это важное отличие!
Показать ещё 1 комментарий
Теги:
class
inheritance

4 ответа

1
Лучший ответ

Открытое наследование означает, что каждый объект производного класса IS одновременно является объектом базового класса (он предоставляет все интерфейсы базового класса). Итак, когда вы пишете:

Base *basePtr = new Derive();

создается новый объект класса Derive, чем указатель на него назначается basePtr а через basePtr вы можете получить доступ ко всем функциям, предоставляемым Base классом.

И если вы затем вызываете любую из виртуальных функций Base класса, например:

basePtr->callSomeVirtualFunction();

будет вызвана функция из фактического класса объекта, как это происходит с деструктором в конце вашей основной функции.

1

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

  • 0
    Спасибо за ответ Олег, не могли бы вы привести пример?
  • 0
    Означает ли это, что он вызывает только общие функции-члены для базового класса и производного класса?
0

Это называется Polymorphism. Это означает, что объект является Derive, а также Base и может использоваться как для обоих. Напр. Если собака является подклассом Animal. Объект собаки можно рассматривать как животное. Все собаки - животные, но не все животные - собака.

Поэтому вы можете назвать собаку животным, поэтому вы можете указать адрес объекта подкласса (Derive) на указатель суперкласса (Base). Но он останется объектом подкласса и будет функционировать как один. Это просто для того, чтобы обмануть компилятор в понимании того, что это объект базы.

Теперь вы можете иметь метод, который может принимать объект (или указатель в точном смысле) базового класса, но может быть передан любым из его подклассов. Здесь вы можете вызывать только методы, которые находятся в базовом классе и могут или не могут быть переопределены в классе вывода.

0

Хммм... Указатели сбивают с толку в начале.

Когда вы вызываете Base *basePtr = new Derive(); , вы создаете экземпляр объекта Derive и просто сохраняете "закладку", где находится этот объект, но с указателем Base.

Когда вы это сделаете, единственные доступные свойства (без трансляции) будут из Base класса.

Почему это используется? Отвлечься. Представьте, что вы кодируете нечто, связанное с кружками, чашками, очками и кувшинами. В основном все типы этих объектов предназначены для хранения какой-либо жидкости. Поэтому я буду называть базовый класс LiquidContainer:

class LiquidContainer
{
  //...
};

class Mug : public LiquidContainer
{
  //...
};

class Glass : public LiquidContainer
{
  //...
};

class Cup : public LiquidContainer
{
  //...
};

class Jug : public LiquidContainer
{
  //...
};

Все остальные унаследованы от LiquidContainer, хотя кувшин, кубок и кружка могут быть созданы в немного более сложном дереве наследования.

Во всяком случае, цель иметь базовый класс и использовать полиморфизм состоит в том, чтобы избежать репликации кода и абстракции thins, позволяя всем LiquidContainer лечиться почти одинаково.

Возьмем, например, более полное определение класса.

class LiquidContainer
{
public:
  LiquidContainer(unsigned int capacity, unsigned int color) : 
    mCapacity(capacity), 
    mColor(color) 
  {
  }

  unsigned int getCapacity() { return mCapacity; }
  unsigned int getColor() { return mColor; }
  virtual char* name() = 0;

protected:
  unsigned int mCapacity;
  unsigned int mColor;
};

class Mug : public LiquidContainer
{
public:
  Mug() :
    LiquidContainer( 250, 0xFFFF0000 ) // 250 ml yellow mug!
  {
  }

  virtual char* name() { return "Mug"; }
};

class Glass : public LiquidContainer
{
public:
  Glass() :
    LiquidContainer( 200, 0x000000FF ) // 200 ml transparent glass!
  {
  }

  virtual char* name() { return "Glass"; }
};

class Cup : public LiquidContainer
{
public:
  Cup() :
    LiquidContainer( 50, 0xFFFFFF00 ) // 50 ml white cup!
  {
  }

  virtual char* name() { return "Cup"; }
};

class Jug : public LiquidContainer
{
public:
  Jug() :
    LiquidContainer( 1500, 0x0000FF00 ) // 1.5 l blue Jug!
  {
  }

  virtual char* name() { return "Jug"; }
};

С помощью этих определений классов вы можете выполнить следующий тест:

#include <iostream>
#include <vector>

int main( int argc, char* argv[] )
{
  std::vector< LiquidContainer* > things;

  things.push_back( new Mug() );
  things.push_back( new Cup() );
  things.push_back( new Glass() );
  things.push_back( new Jug() );

  for ( auto container : things )
  {
    std::cout << "This is a '" << container->name() << "' with capacity of " << container->getCapacity() << "ml and color " << container->getColor() << std::endl;
  }

  return 0;
}

Эта небольшая программная продукция

This is a 'Mug' with capacity of 250ml and color 4294901760
This is a 'Cup' with capacity of 50ml and color 4294967040
This is a 'Glass' with capacity of 200ml and color 255
This is a 'Jug' with capacity of 1500ml and color 65280

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

Ещё вопросы

Сообщество Overcoder
Наверх
Меню