У меня есть следующие занятия:
class A {
};
class B : public A {
int num;
};
в основном у меня есть:
int main() {
A* vec; // A is a class with pure virtual functions
vec = new B[2]; // want to create a vector of B
}
vec [0] определен правильно, но vec [1] равен NULL. почему это не выделило мне подходящую память?
Я не хочу менять основные линии. просто заставь это работать.
(Я знаю, что могу изменить основное на: B * vec = new B [2], но я не хочу)
любая помощь приветствуется!
Вы не можете обрабатывать массивы полиморфно, язык C ++ не поддерживает его. Выражение vec[x]
использует арифметику указателей для определения местоположения элемента. Если вы обращаетесь к нему через указатель базового класса, он не будет работать, если размер объектов будет меняться каким-либо образом.
Например, у вас есть базовый класс размером 4 байта, а подкласс размером 8 байтов.
base *a = new child[4];
Когда вы получаете доступ a[1]
компилятор вычисляет смещение, используя размер базового класса. В этом случае смещение составляет 4 байта, которые заканчиваются указанием на середину первого элемента.
Я рекомендую использовать std::vector
или же std::array
указателей с соответствующим умным указателем.
// For arrays that needs to be resized (requires delete for each new)
std::vector<A*> vec(5, NULL);
for(int i = 0; i < vec.size(); i++)
{
vec[i] = new B();
}
// for arrays that are fixed in size (requires delete for each new)
std::array<A*, 5> vec;
for(int i = 0; i < vec.size(); i++)
{
vec[i] = new B();
}
// for arrays that are fixed in size with smart pointers
// no delete needed
std::array<std::unique_ptr<A>, 5> vec;
for(int i = 0; i < vec.size(); i++)
{
vec[i].reset(new B());
}
если вы хотите, чтобы он был полиморфным, просто создайте массив указателей
new A*[array_size]
Этот фрагмент кода иллюстрирует проблему, с которой вы столкнулись.
#include <iostream>
using namespace std;
class A {
};
class B : public A {
int num;
};
int main() {
A* vec; // A is a class with pure virtual functions
vec = new B[2]; // want to create a vector of B
cout << sizeof(vec) << endl;
cout << sizeof(*vec) << endl;
cout << sizeof(vec[2]) << endl;
cout << sizeof(new B()) << endl;
}
В арифметике указателей размер типа выделенного указателя — это то, что используется для приращения, а не размер истинного типа объекта, на который он указывает. Проще говоря, язык не поддерживает полиморфные массивы. Это просто объяснение почему.