Полиморфизм и указатели на массивы [дублировать]

StackOverflow https://stackoverflow.com/questions/1411844

Вопрос

На этот вопрос уже есть ответ здесь:

У меня есть класс А:

class A
{
    public:
        virtual double getValue() = 0;
}

И класс В:

class B : public A
{
    public:
        virtual double getValue() { return 0.0; }
}

И затем в main() я делаю:

A * var;
var = new B[100];
std::cout << var[0].getValue(); //This works fine
std::cout << var[1].getValue(); //This, or any other index besides 0, causes the program to quit

Если вместо этого я сделаю:

B * var;
var = new B[100];
std::cout << var[0].getValue(); //This works fine
std::cout << var[1].getValue(); //Everything else works fine too

Все компилируется нормально, но, возможно, кажется, что с моим полиморфизмом что-то не так?Я озадачен.

Это было полезно?

Решение

Вы не можете обрабатывать массивы полиморфно, поэтому, хотя new B[100] создает массив B объектов и возвращает указатель на массив - или, что эквивалентно, на первый элемент массива - и хотя допустимо присваивать этот указатель указателю на базовый класс, недопустимо рассматривать это как указатель на массив A Объекты.

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

Другие советы

Проблема не в полиморфизме, а в том, как вы работаете с памятью.Оператор [] продвинет вас по массиву на размер байт (A) в первом случае и на размер байт (B) во втором случае.Поскольку объекты относятся к типу B, A * не указывает на правильное местоположение в памяти.

Вот еще один способ взглянуть на это

char * var;
var = (char*) new B[100];
std::cout << ((A*)var[0]).getValue(); //This works fine
std::cout << ((A*)var[1]).getValue(); //This will fail
std::cout << ((A*)var[sizeof(B)]).getValue(); // should work

Вы не выделили объекты в массиве:

for (int i=0;i<100;i++)
  var[i] = new B;

(хотя, возможно, я путаю C ++ и C #)

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top