2016-11-20 22 views
2

Поэтому у меня есть классы User и Job:Успокойтесь, если у 2 классов есть поле, указывающее друг другу?

class User { 
string user_name; 
Job* job; 
}; 

class Job { 
string job_type; 
int salary; 
User* user; 
}; 

Существуют ли какие-либо проблемы с этим видом дизайна? У меня большое количество Job s и User s, и я хочу получить быстрый доступ к заданию пользователя или к пользователю, у которого есть работа. Это нормально, что у этих классов есть поля, которые друг к другу подходят друг другу?

+2

Fyi ваш пример, вероятно, * begging * для ['std :: shared_ptr'] (http: // ru.cppreference.com/w/cpp/memory/shared_ptr) и ['std :: weak_ptr'] (http://en.cppreference.com/w/cpp/memory/weak_ptr) вместо того, чтобы терять вокруг сырых указателей, как вы , Нажмите на эти предоставленные ссылки, чтобы узнать больше о них. – WhozCraig

+0

Я бы использовал радикально другой подход с базой данных SQL и тремя таблицами «пользователь», «job_type» и «job», причем последний установил связь между двумя другими, так что любой пользователь может иметь от 0 до n заданий. В вашем коде на C++ у вас больше не будет отдельных классов 'User' и' Job', но неизменяемых классов результатов запроса, полученных непосредственно из соответствующих JOIN. Любые изменения происходят через более или менее явные UPDATE или INSERT. Я нашел такие архитектуры бесконечно проще в использовании, именно потому, что они освобождают вас от этой точной проблемы с указателем. –

ответ

3

Все в порядке. Вы должны быть осторожны, чтобы управлять указателями осторожно, чтобы избежать утечек, например. Но это вполне разумно.

+0

Я поддержал, но я был бы больше обеспокоен оборванными указателями, чем утечками памяти. Если вас беспокоит утечка памяти, это означает, что эти указатели владеют необработанными указателями, которые были распределены динамически, что обычно не является хорошей идеей. –

+0

Вы можете использовать интеллектуальные указатели. Тогда вам нужно будет беспокоиться о утечках, которые могут исходить из круговых ссылок. Вот здесь и появляются слабые указатели. Http://stackoverflow.com/questions/12030650/when-is-stdweak-ptr-useful – Waxrat

0

Обычная ситуация в мире oop. Например, типичная архитектура графического интерфейса использует такой подход аналогичным образом:

  1. Виджет знает о своем родителе. Он сохраняет указатель на родительский.

  2. Соединение виджет знает о его г заказанных детей (виджет)

Я понимаю, что такой пример далеко от вашего поста. Он просто показывает случай.

Я не знаю точной архитектуры вашего приложения. Но, может быть, класс Job не должен знать о пользователе? Это снижает дополнительные отношения и упрощает управление памяти (вместо использования для лучшего управления совместно и слабых указатели)

1

Пока User не владеет Job и Job не владеют User, то это прекрасно.

Например, возможно, вы создаете коллекции Job с и User сек авансовые и затем хотите создать ассоциации между ними:

#include <string> 
#include <vector> 

class Job; 

class User { 
    std::string user_name; 
    Job* job; 
    public: 
    explicit User(const std::string& user_name) : user_name(user_name) {} 
    void setJob(Job& job) { this->job = &job; } 
}; 

class Job { 
    std::string job_type; 
    int salary; 
    User* user; 
    public: 
    Job(const std::string& job_type, int salary) : job_type(job_type), salary(salary) {} 
    void setUser(User& user) { this->user = &user; } 
}; 

void recruit(User& user, Job& job) { 
    user.setJob(job); 
    job.setUser(user); 
} 

int main() { 
    auto jobs = std::vector<Job>{ {"Tinker", 10'000}, {"Tailor", 20'000}}; 
    auto users = std::vector<User> {User{"George"}, User{"Percy"}}; 
    recruit(users[0], jobs[1]); 
    recruit(users[1], jobs[0]); 
} 

Пока коллекции User с и Job с разрушаются при в то же время нет опасности оборванных указателей. Может быть предпочтительнее, если указатели были указателями const.

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

0

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

Я считаю это неприемлемым, если нет очень веских причин (например, требований к производительности), чтобы сделать это таким образом.

Это круговая зависимость, которая ухудшает читаемость и проверяемость кода. Но моя главная проблема заключается в том, что будет очень сложно поддерживать соответствие этих ссылок.

В качестве альтернативы, я бы предоставил только одну ссылку, скажем, у пользователя есть указатель на Job. Теперь, если у вас есть задание и вы хотите найти соответствующих Пользователей, вы все равно можете выполнить поиск по всем пользователям и найти те, у которых есть указатель на это задание. Конечно, это менее эффективно, чем прямой указатель, но во многих случаях это не имеет значения. Что может быть более важным, так это то, что несоответствия не могут возникнуть.