Вернуть объект в векторный указатель, класс объекта в пространство имен

#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:

Несколько разных подходов:

  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

  2. Например, 1) вы храните указатели в своем векторе, но не выделяете Patient экземпляры в куче :

     std::vector<Healt::Patient*> patients;
    Health::Patient p1 ("John", "April");
    p1.set("1234");
    patients.push_back(amp;p1);
      

    Это сопряжено с риском того, что patients он может выйти за пределы области видимости, но вы все равно разыменовываете указатели, переданные вашему Hospital экземпляру, например

  3. Не используйте вектор, хранящий указатели на объекты:

     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 , например