#c #object #vector
#c #объект #вектор
Вопрос:
Основная проблема заключается в том, как добавить объект пациента в вектор указателя. Класс Patient находится в пространстве имен Health. У пациента есть имя, фамилия и номер (я использовал set и get). Вектор указателей, которые я должен поместить в больницу.
основной раздел
vector<Health::Patient*> patients;
Health::Patient p1("John", "April");
p1.set("1234");
cout<<p1.get();
Health::Patient p2("George", "Best");
p1.set("2351");
patients.push_back(p1); // in this line push_back doesn't work
Hospital h1("DontGoThere", patients);
Должен ли я создать новую функцию для добавления объекта patient в вектор?
Комментарии:
1. Вы хотите
vector<Health::Patient> patients;
(без звездочки).2. Если вы действительно хотите
patients
хранить указатели наPatient
, вам также нужноp1
иметь этот тип:Health::Patient* p1 = new Health::Patient("John", "April");
но вам нужно явно освобождать память, когда элемент извлекается из вашего вектора, делая это таким образом3. @Momo Тебе нужно это вызвать
p1->set("2351")
. Но подумайте о том, чтобы не использовать вектор указателей, как предложил @PaulSanders — тогда вам не нужно так сильно заботиться об управлении памятью. Затем вам нужно настроить конструкторHospital
, напримерHospital::Hospital(std::string str, std::vector<Health::Patient> amp;patients)
4. Задача состоит в том, чтобы использовать указатели , тогда задача неправильная.
5. Задача состоит в том, чтобы научить вас плохому C .
Ответ №1:
Несколько разных подходов:
-
Сохранить
patients
в качестве вектораHealth::Patient*
std::vector<Healt::Patient*> patients; Health::Patient *p1 = new Health::Patient("John", "April"); p1->set("1234");
Таким образом, вы должны сами позаботиться о том, чтобы выделенная память для каждого экземпляра
Patient
была должным образом освобождена, например:// delete last container element std::vector<Health::Patient*>::iterator itr = patients.back(); if (*itr) { delete *itr; } patients.pop_back();
И это становится действительно запутанным, если экземпляр
Hospital
, например, также содержит указатель на освобожденный экземплярPatient
-
Например, 1) вы храните указатели в своем векторе, но не выделяете
Patient
экземпляры в куче :std::vector<Healt::Patient*> patients; Health::Patient p1 ("John", "April"); p1.set("1234"); patients.push_back(amp;p1);
Это сопряжено с риском того, что
patients
он может выйти за пределы области видимости, но вы все равно разыменовываете указатели, переданные вашемуHospital
экземпляру, например -
Не используйте вектор, хранящий указатели на объекты:
vector<Health::Patient> patients; Health::Patient p1("John", "April"); p1.set("1234"); patients.push_back(p1); // adjust Constructor of `Hospital` so it takes `std::vector<Patient>` // as argument (or a reference to it)
Преимущество здесь в том, что вы можете просто вызвать
patients.pop_back()
, чтобы удалить последний элемент — нет необходимости освобождать память, выделенную вами в куче. Память автоматически освобождается, когда вектор выходит за пределы области видимости.
Не зная всего вашего кода, я рекомендую, чтобы Hospital
вам принадлежали фактические экземпляры (или копия) Patient
, и вы напрямую добавляли туда свои объекты, не имея локального контейнера, кроме одного в качестве члена Hospital
(особенно, если это контейнер указателей)
void Hospital::addPatient(Health::Patient p) {
m_patients.push_back(p);
}
Health::Patient p1("John", "April");
p1.set("1234");
h1.addPatient(p1);
Редактировать: Настаивая на использовании указателей
Для подхода с указателем вы должны убедиться, что он Hospital
принимает право собственности на переданный Patient
экземпляр, поэтому управление памятью обрабатывается только там:
// m_patients now of type std::vector<Health::Patient*>
void Hospital::addPatient(Health::Patient* p) {
if (p) {
m_patients.push_back(p);
}
}
Health::Patient *p1 = new Health::Patient("John", "April");
p1->set("1234");
// Hospital takes ownership
h1.addPatient(p1);
p1 = NULL;
При таком подходе еще лучше вообще не использовать переменную-указатель p1
и усовершенствовать ваш конструктор Patient
, чтобы он сразу создавал нужный объект, и вам не нужно было гарантировать, что p1
вы больше не сможете получить к нему доступ.
h1.addPatient(new Health::Patient("John", "April", "1234"));
Как показано в 1) вам нужно убедиться, что память правильно освобождена — деструктор Hospital
был бы подходящим местом для освобождения всех оставшихся элементов внутри m_patients
, например