0

Я, вероятно, будет путать себя во время написания этого, извините заранее:массив Random Access C++

Есть ли способ я могу получить доступ место в динамическом массиве (увеличиваем указатель массива) указателей с использованием sizeof() объект, который находится в массиве?

Например: У меня есть динамический массив базового класса типа Student, заполненный объектами производного класса (Graduate, Depgraduate).

Из-за этого я не могу просто пройти через свой массив в нормальном режиме, чтобы отображать информацию, потому что фактические объекты Выпускники и бакалавриаты разных размеров, чем Student. Каждый шаг массива будет перемещаться sizeof(Student), когда фактические объекты больше.

В зависимости от типа студента я делаю (это для Graduate):

Student *student = new Graduate(undergrad, fName, lName, major, idNum, arr2, cSize, 
     degreeType, thesis); 
arr[i] = student; 

Где arr был объявлен: Student *arr = new Student[size];

Используя мой массив я создал это в цикле:

if (!students[i].getGradStatus()){ 
    handleGraduate(&students[i], i); 
    step = step + sizeof(Graduate); 
} 
else if (students[i].getGradStatus()){ 
    handleUndergraduate(&students[i], i); 
    step = step + sizeof(Undergraduate); 
} 

Я пытался придумать способ изменить размер шага. Я не думаю, что это будет работать с циклом for, но цикл while может быть другим. В основном я пытаюсь найти что-то похожее на файл seekg(), но вручную на массив.

И как я заметил, всем нравится подвергать сомнению использование динамических массивов над векторами, поэтому позвольте мне сказать, что я не могу использовать векторы в этом проекте (STL не допускается :(). И я должен использовать полиморфизм, таким образом почему у меня есть указатель на массив типа Student холдингового производных объекты класса.

+0

И вот почему классы без листьев в полиморфной иерархии должны быть абстрактными. .. –

+0

Повесьте, так что ваш массив содержит фактические объекты, а не указатели на них? Для вашего массива, заполняющего размер, здесь имеет смысл указатель, а не объект Student. Я что-то упускаю? –

+0

Обычно это делается с помощью массива указателей ('Student ** arr'). Затем каждый элемент может указывать на другой класс в иерархии. То, что вы говорите, вы хотите сделать, возможно, но не для слабонервных. – 1201ProgramAlarm

ответ

2

Вы не можете хранить объекты разного размера в таком массиве. При попытке скопировать производный тип как Graduate над базовым типом как Student вы получите то, что известно как нарезки из-за различия в размерах объекта (части могут получить сколы).

Для этого вам нужно хранить Student*

class Student 
{ 
    std::string name; 
public: 
    Student(const std::string& name): name(name) {} 
    virtual ~Student() {} // virtual destructor 

    virtual void handle() = 0; // implementation must override this 

    std::string get_name() const { return name; } 
}; 

class Graduate 
: public Student 
{ 
public: 
    Graduate(const std::string& name): Student(name) {} 
    virtual void handle() { std::cout << "Handling Graduate" << '\n'; } 
}; 

class UnderGraduate 
: public Student 
{ 
public: 
    UnderGraduate(const std::string& name): Student(name) {} 
    virtual void handle() { std::cout << "Handling UnderGraduate" << '\n'; } 
}; 

int main() 
{ 
    Student** students = new Student*[3]; 

    students[0] = new Graduate("Wendy"); 
    students[1] = new UnderGraduate("Bob"); 
    students[2] = new Graduate("Rachel"); 

    for(int i = 0; i < 3; ++i) 
    { 
     std::cout << students[i]->get_name() << '\n'; 
     students[i]->handle(); // polymorphic function (virtual) 
    } 

    delete[] students; // clean up or (better) use a smart pointer 
} 

Output (указателей на Students.):

Wendy 
Handling Graduate 
Bob 
Handling UnderGraduate 
Rachel 
Handling Graduate 
+0

Ahhhhhhhhhhh это работает сейчас. Пришлось изменить мои' .' на '->' Я пытался заставить это работать уже почти 2 дня. Большое спасибо. Я бы хотел прояснить, что при передаче этого массива функции func (students) 'и' void func (Студенческие ** студенты) ' – Alyssa

+0

Как насчет того, когда производный класс имеет переменную-член, а получатели и сеттеры, к которым я должен получить доступ? Могу ли я послать этот указатель на переменную, предназначенную для хранения этого типа объекта? Как« Выпускник stu = student [i]; ' – Alyssa

+0

@Alyssa Весь смысл полиморфизма заключается в том, что вам не нужно знать точный тип. Вместо кода, требующего знать точный тип объектов, чтобы знать, как работать с ними, объекты работают сами по себе. – Galik

1

Изменить ваш массив быть массивом студенческих указателей вместо объектов Student.

Student **arr = new Student*[size]; 

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

+0

Я только что оставил комментарий об этом выше :( – Alyssa

1

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

Сделать массив указателей ученика вместо этого, Student **arr. Указатели имеют фиксированный размер, и они указывают на любой из производных типов учеников, поэтому вам не нужно беспокоиться об их размерах.


Student **student = new Student*[size]; 
... 
student[i] = new Graduate(...); 

Это должно работать.

+0

, но когда мне нужно получить доступ к информации, предположим, .., один из указателей Graduate, которые я создал, как мне получить к нему доступ? 'student [i] .getName() ; 'does not work – Alyssa

+1

@Alyssa Теперь вы работаете с указателями. Чтобы получить доступ к данным элемента через указатель, напишите' student [i] -> getName(); '. – aslg