C ++ выделения памяти для списка абстрактных объектов класса

голоса
0

Мое понимание массивов C ++ является то, что вы не можете выделить массив абстрактных объектов класса, так как C ++ не знает, как выделить память для еще-к-быть-решено типа класса.

Я собрал маленький пример, который меня смущает немного, поэтому хотел спросить немного больше,

#include <iostream>

class Animal {
public:
  virtual void hello() {}
};

class Dog : public Animal {
public:
  void hello() { std::cout << woof! << std::endl; }
};

class Cat : public Animal {
public:
  void hello() { std::cout << meow << std::endl; }
};

int main() {
  Dog d;
  d.hello(); // prints woof!

  Cat c;
  c.hello(); // prints meow

  // how are we allowed to create an array of abstract class?
  // doesn't c++ need to know how to allocate memory for any abstract
  // class in order to do this?
  Animal creatures[5];
  creatures[0] = d;
  creatures[1] = c;
  creatures[4] = d;

  // prints 6Animal
  std::cout << typeid(creatures[0]).name() << std::endl;

  // this appears to call the Animal hello(), which does nothing
  creatures[1].hello();
}

Вопросов

  1. Как C ++ в состоянии выделить память для этого массива? Почему это не жалуются?
  2. Оказывается, что-то об этом не подведет из-за обработки всех объектов, как животные, а именно: не правильно делать полиморфизм. Что именно происходит, и почему? Должен ли я просто выделить для списка указателей, чтобы сделать это правильно, а?

Благодарность!

Задан 19/03/2020 в 21:55
источник пользователем
На других языках...                            


1 ответов

голоса
2

Animalне является абстрактным. Он не содержит чистых виртуальных функций - членов. При назначении cи dна элементы creaturesвас нарезка их.

Если вместо этого, Animal::helloбыли объявлены чисто виртуальными, т.е.

class Animal {
public:
  virtual void hello() = 0;
};

Animal creatures[5]будет не компилироваться , так как Animalтеперь абстрактно.


По второму вопросу выполнения полиморфизма в C ++ работает только со ссылками и указателями. Если вы знакомы с языками , как Java или Python , это может показаться немного странным на первый, но помните , что в этих языках все переменные типов класса являются указателями (или указатель , как вещи, так или иначе).

В C ++, Animal creatures[5]будет выложена в чем - то памяти , как это:

creatures
+--------+--------+--------+--------+--------+
| Animal | Animal | Animal | Animal | Animal |
+--------+--------+--------+--------+--------+

В Java, Animal[] creatures = new Animal[5];будет выложена в памяти , как это:

+-----------+   +---+---+---+---+---+
| creatures +-->+ 0 | 1 | 2 | 3 | 4 |
+-----------+   +-+-+-+-+-+-+-+-+-+-+
                  |   |   |   |   |
       +--------+ |   |   |   |   | +--------+
       | Object +<+   |   |   |   +>+ Object |
       +--------+     |   |   |     +--------+
                      v   |   v
               +------+-+ |  ++-------+
               | Object | |  | Object |
               +--------+ |  +--------+
                          v
                     +----+---+
                     | Object |
                     +--------+

Там нет прямого аналога для массивов C ++ в таких языках, как Java или Python

Это означает , что все объекты в C ++ массив должен быть точно таким же типом. Если вы хотите создать что - то вроде массива Java, вы должны использовать указатели. Вы должны использовать стандартные классы смарт-указатель std::unique_ptrи std::shared_ptr. т.е.

std::shared_ptr<Animal> creatures[5];
creatures[0] = std::make_shared<Dog>();
creatures[1] = std::make_shared<Cat>();

creatrues[0]->hello(); // prints "woof!"
creatures[1]->hello(); // prints "meow"
Ответил 19/03/2020 в 22:00
источник пользователем

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more