2013-09-06 5 views
0

При работе над программными проектами в качестве хобби у меня был прогресс, который замедлялся или полностью останавливался во время процесса проектирования много раз. Обычно я сталкиваюсь с теми же проблемами, с которыми я уже сталкивался раньше. Одной из таких повторяющихся проблем о разрешении объекта знать, что объект должен это связаться или какой объект является его владельцем:C++: распространение информации от дочернего объекта до родительского объекта

Предположим, что у нас есть экземпляр класса Corporation имени startup, где работают один класс Supervisor объект и несколько классов Employee объектов. Надзорный орган несет ответственность за назначение задач сотрудникам и помощь сотрудникам при обращении за помощью. Но сотрудники должны знать , который является их руководителем, чтобы сообщить, что они закончили работу над своим заданием или попросили чего-то.

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

  1. сделать экземпляр Supervisor глобально доступным, и есть все Employees просто называют этот экземпляр непосредственно: Как избежать глобал, как правило, хорошая идея, но это могло быть исключением? Я думаю, что нет, и если бы startup когда-либо вырастет, чтобы иметь более одного менеджера, возникнут проблемы.
  2. Добавление члена static Supervisor *supervisor в класс Employee: это позволяет избежать использования и проблем, связанных с глобальным доступом, но сохраняет неспособность сотрудников сообщать различным менеджерам, когда растет startup.
  3. Добавление Supervisor *supervisor элемента к Employee класса, и передавая Supervisor указатель к каждому Employee в качестве параметра конструктору сотрудника: Очень гибкий, но неэффективен с точки зрения использования памяти, когда Employee не имеет много переменных-членов.
  4. Передача Supervisor указатель в качестве параметра в каждом вызове Employee функций-членов, где Employee может понадобиться знать, кто является supervisor: Самый гибкий, но, вероятно, еще менее эффективным, чем решение 3, и почти все функции-члены будут требовать от руководителя , что приводит к дополнительным накладным расходам и ненужным зависимостям.
  5. Выполнение Employee шаблона класса с одним аргументом не-типа Supervisor *S: Это будет так же эффективно, как решение 1 или 2, но гораздо более гибкое. Однако, хотя число сотрудников в startup может быть изменено во время выполнения, добавление большего количества супервизоров в startup во время выполнения было бы невозможным, если в момент компиляции не создаются дополнительные супервизоры, но остаются неактивными. Кроме того, я понятия не имею, как создать конструктор копирования, который в качестве аргумента принимает одного сотрудника другого, но похожего (созданного шаблоном) типа.
+0

Мое текущее любимое решение - номер 5, при условии, что можно создать конструктор рабочей копии, так как мой проект может работать с фиксированным набором эквивалентов объектов «Manager ». – jms

+2

Вы пришли к этому вопросу после профилирования и определения того, что указатели 'Supervisor *' действительно являются значительным источником потери памяти в вашей программе по сравнению с другим использованием памяти? В противном случае это кажется ясным примером преждевременной оптимизации, и вы не должны позволять ему «замедлять или полностью останавливать» вашу разработку на этапе проектирования. Идите с простейшим решением, концептуально правильным - № 3. Если это окажется проблемой, измените свое решение позже. – svk

+0

Не является ли надзор работником? Как насчет разных отделов? Имеются ли у обоих HR и развития один и тот же руководитель? Что, если вы разделите развитие на несколько команд? Единственное разумное решение - № 3, и у вас никогда не будет достаточно сотрудников, чтобы сделать один указатель на одного сотрудника имеющим какое-либо значение. Как только вы это сделаете, вы используете базу данных, поэтому вам не нужно одновременно удерживать всех сотрудников в памяти. – molbdnilo

ответ

1

Предоставление Employee указателем на его Supervisor является традиционным методом организации обратных вызовов или отчетов о ходе работы. (Это ваше решение номер три.) Это всего лишь один указатель. Если у вас достаточно сотрудников, которые вас беспокоят в отношении использования памяти (т. Е. Несколько тысяч из них), вы можете уменьшить размер, используя меньший дескриптор, а не указатель. То есть, что-то вроде

typedef uint8_t SupervisorHandle; 

class Employee { 
    private: 
    SupervisorHandle s; 

    Supervisor& getSupervisor() { 
     return startup.getSupervisor(s); 
    } 
    // ... 
}; 

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

Вы уже заметили, что ваши ответы 1 и 2 ограничивают вас одним Supervisor: если вы собираетесь это сделать, почему у вас вообще есть класс? Вариант 4, имеющий Supervisor, прошедший в каждом методе, на самом деле не улучшается: теперь Corporation должен иметь карту, связывающую каждые Employee справа Supervisor и искать на этой карте для каждого вызова. Представление такого рода накладных расходов, чтобы сохранить небольшую память, - это то, что вы делали бы, только если бы вы были отчаянно коротки. Вариант 5 ограничивает вас статически выделенным Supervisor с. Вам также необходимо создать без шаблона класс EmployeeBase для шаблона класса Employee, и если только Employee уже использует наследование, служебные данные vtable уничтожат вашу память.

Смежные вопросы