1

Тема: Smart pointer: shared_ptr<>

Задача: Створити клас SoftwareEngineer, що містить поля:
●    string name;
●    string position (Junior Developer, Developer, Senior Developer);
●    int salary;
●    string currentProject;
Описати інтерфейс класу по необхідності (Конструктори, аксесори та мутатори для полів, метод виводу інформації).
Свторити глобальні функції:
●     ShowData() - виводить інформацію про конкретного програміста;
●    ChangeData() - запитує у користувача дані та заповнює ними поля класу, використовуючи відповідні сеттери.
Функції повинні приймати та повертати shared_ptr<>.

Я реалізувала її так:

Прихований текст
#include <iostream>
#include <string>
#include <memory>

using namespace std;

class SoftwareEngineer
{
    string name;
    string position;
    int salary;
    string current_project;

    bool ValidInputString(string str)
    {
        if (str == "" || str == " ")
            return false;

        for (int i = 0; i < str.length(); ++i)
            if (!isalpha(str[i]))
                return false;

        return true;
    }

    bool IsValidDigit(int number)
    {
        if (number < 0)
            return false;

        string str = to_string(number);

        for (int i = 0; i < str.length(); ++i)
            if (!isdigit(str[i]))
                return false;

        return true;
    }
public:
    SoftwareEngineer()
    {
        name = "no name";
        position = "no position";
        salary = 0;
        current_project = "no project";
    }

    SoftwareEngineer(string name, string position, int salary, string current_project)
    {
        this->name = name;
        this->position = position;
        this->salary = salary;
        this->current_project = current_project;
    }

    void SetName(string name)
    {
        if (ValidInputString(name))
            this->name = name;
    }

    string GetName()
    {
        return name;
    }

    void SetPosition(string position)
    {
        if (ValidInputString(position))
            this->position = position;
    }

    string GetPosition()
    {
        return position;
    }

    void SetSalary(int salary)
    {
        if (IsValidDigit(salary))
            this->salary = salary;
    }

    int GetSalary()
    {
        return salary;
    }

    void SetCurrentProject(string current_project)
    {
        if (ValidInputString(current_project))
            this->current_project = current_project;
    }

    string GetCurrentProject()
    {
        return current_project;
    }

    void Show()
    {
        cout << "Name: " << name << "\n";
        cout << "Position: " << position << "\n";
        cout << "Salary: " << salary << "\n";
        cout << "Current project: " << current_project << "\n";
    }
};

void Input(shared_ptr<SoftwareEngineer> &software_engineer)
{
    string temp;
    cout << "\nName: ";
    getline(cin, temp);
    software_engineer->SetName(temp);

    cout << "\nPosition: ";
    getline(cin, temp);
    software_engineer->SetPosition(temp);

    int salary = 0;
    cout << "\nSalary: ";
    cin >> salary;
    software_engineer->SetSalary(salary);

    cin.ignore(256, '\n');
    cout << "\nCurrent project: ";
    getline(cin, temp);
    software_engineer->SetCurrentProject(temp);

}


shared_ptr<SoftwareEngineer> ShowData(shared_ptr<SoftwareEngineer> *software_engineers, int index_engineer, int number_engineers)
{
    --index_engineer;
    if (index_engineer < 0 || index_engineer >= number_engineers)
        cout << "\nSoftware engineer with such index doesn't exist\n";
    
    software_engineers[index_engineer]->Show();

    return software_engineers[index_engineer];
}

shared_ptr<SoftwareEngineer> ChangeData(shared_ptr<SoftwareEngineer> *software_engineers, int index_engineer, int number_engineers)
{
    --index_engineer;
    if (index_engineer < 0 || index_engineer >= number_engineers)
        cout << "\nSoftware engineer with such index doesn't exist\n";

    Input(software_engineers[index_engineer]);

    return software_engineers[index_engineer];
}

int main()
{
    const int NUMBER_ENGINEERS = 5;
    shared_ptr<SoftwareEngineer> software_engineers[NUMBER_ENGINEERS];

    for (int i = 0; i < NUMBER_ENGINEERS; ++i)
    {
        cout << "\nEnter the information about " << i+1 <<" software engineer:\n";
        Input(software_engineers[i]);
        system("cls");
    }

    cout << "\nEnter the index of the engineer, the information about which you show: ";
    int pos_engineer;
    cin >> pos_engineer;

    shared_ptr<SoftwareEngineer> show_engineer = ShowData(software_engineers, pos_engineer, NUMBER_ENGINEERS);

    system("cls");
    cout << "\nEnter the index of the engineer, the information about which you what change: ";
    cin >> pos_engineer;

    shared_ptr<SoftwareEngineer> change_engineer = ChangeData(software_engineers, pos_engineer, NUMBER_ENGINEERS);
    cout << "\n\tChange engineer:\n";
    change_engineer->Show();

    cout << "\n\tAll engineers: \n";
    for (int i = 0; i < NUMBER_ENGINEERS; ++i)
        software_engineers[i]->Show();

    return 0;
}

Але програма вилітає ось тут:

void SetName(string name)
    {
        if (ValidInputString(name))
            this->name = name;
    }

а точніше на рядку:

this->name = name;

В чому може бути проблема?

2

Re: Smart pointer: shared_ptr<>

Ви неправильно використовуєте shared_ptr (власне, ви це самі розумієте, судячи з заголовка).
shared_ptr реалізує саме вказівник - проголошення shared_ptr<SoftwareEngineer> не створює жодного об'єкта SoftwareEngineer! Вони створюються функцією make_shared:

for (int i = 0; i < NUMBER_ENGINEERS; ++i) {
  software_engineers[ i ] = make_shared<SoftwareEngineer>();
  ...//введення даних
}

Але shared_ptr потрібен, коли один об'єкт утримується кількома іншими об'єктами, і є ризик його загубити. Наприклад, якщо в кожного інженера є довідник з контактами кількох інших (посиланнями), або є інші об'єкти "фірма" і "проект" з такими контактами і т.д. Навіть не так: shared_prt реалізує агрегацію, коли один елемент може належати кільком сутностям. А тут цілком можна обійтися простими об'єктами, або ж unique_ptr (передавати в функції треба простий вказівник через get).

Подякували: pika19891

3

Re: Smart pointer: shared_ptr<>

Дивно, але, на жаль, про make_shared нам нічого не розповідали.