Динамические структуры в C ++ - PullRequest
2 голосов
/ 24 мая 2011

Я запускаю симуляцию, в которой у меня есть объекты класса, которые используют разные модели.Эти модели выбираются случайным образом для некоторых объектов класса и специально для некоторых объектов.Эти объекты взаимодействуют друг с другом, для чего я использую структуры (также известные как struct) в C ++, которые имеют некоторые

  1. стандартные переменные и
  2. некоторые дополнительные переменные, которые зависят от моделей, которые связываются объектыдруг с другом есть.

Итак, как я могу это сделать?

Заранее спасибо.

Ответы [ 6 ]

1 голос
/ 24 мая 2011

Все экземпляры структуры или класса имеют одинаковую структуру. К счастью, есть некоторые приемы, которые можно использовать для «симуляции» того, что вы пытаетесь сделать.

Первый прием (который также может быть использован в C) - это использование объединения, например ::100100

struct MyStruct
   {
   int field1;
   char field2;
   int type;
   union
      {
      int field3a;
      char field3b;
      double field3c;
      } field3;
   };

В объединении все члены занимают одно и то же место в памяти. Как программист, вы должны быть осторожны. Вы можете получить из объединения только то, что вставили. Если вы инициализируете одного члена объединения, но читаете другого члена, вы, вероятно, получите мусор (если вы не хотите делать некоторые низкоуровневые хаки, но не делайте этого). это если вы не очень опытный).

Профсоюзы часто объединяются с другим полем (вне союза), которое указывает, какой член фактически используется в профсоюзе. Вы можете считать это вашим «состоянием».

Второй трюк - использование шаблона 'state' (см. http://en.wikipedia.org/wiki/State_pattern).. Из внешнего мира класс контекста выглядит всегда одинаково, но внутри разные состояния могут содержать информацию разного рода.

Несколько упрощенный подход к состоянию - использовать простое наследование и использовать динамическое приведение типов. В зависимости от вашего «условия» используйте другой подкласс и выполните динамическое приведение, чтобы получить конкретную информацию.

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

class Country
   {
   ...
   };

class Republic : public Country
   {
   public:
      const string &getPresident() const;
      const string &getVicePresident() const;
   };

class Monarchy : public Country
   {
   public:
      const string &getKing() const;
      const string &getQueen() const;
   };

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

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

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

1 голос
/ 24 мая 2011

Существует несколько общих подходов к «динамическим» атрибутам / свойствам в языках, и некоторые из них, как правило, хорошо работают в C ++.

Например, вы можете создать класс C ++ с именем "MyProperties", который имеет разреженный набор значений, и ваш MyStructureClass будет иметь свои хорошо известные члены плюс один экземпляр MyProperties, который может иметь ноль или больше значений.

Точно так же языки, такие как Python и Perl, широко используют ассоциативные массивы / словари / хэши для достижения этой цели: ключ (строка) однозначно определяет значение. В C ++ вы можете индексировать свой класс MyProperties с помощью строки или любого другого типа (после перегрузки operator[]()), а значение может быть string, MyVariant или любым другим указателем или типа, что вы хотите проверить. Значения динамически добавляются в родительский контейнер по мере их назначения (например, класс «запоминает» последнее заданное значение, однозначно идентифицируемый ключом).

Наконец, в «старые времена» то, что вы описываете, обычно делалось для распределенной обработки приложений: вы определили C- struct с «хорошо известными» (типизированными) полями / членами, а последний Поле было char* членом. Затем этот элемент char* идентифицирует начало сериализованного потока байтов, которые были также частью этого struct (вы просто сериализовали этот массив символов, когда вы упорядочили struct по системам) , В контексте C ++ вы также можете динамически извлекать ваши значения из этого потокового буфера char* по требованию доступа (который по логике должен «принадлежать» классу). Это сработало для сортировки по системам, потому что размер структуры был размером всего (включая последний char* член), но «распределение» для этой структуры было намного больше (например, размер самой структуры, которая была логически это «заголовок», плюс определенное количество байтов после этого заголовка, который представляет «полезную нагрузку» и который был проиндексирован последним членом, char* элементом.) Таким образом, это был непрерывный блок памяти struct, с динамическим размером. (Это также будет работать в C ++, пока вы передаете по ссылке, и никогда по значению.)

1 голос
/ 24 мая 2011

Вы можете взломать:

  • препроцессор;
  • шаблон метапрограммирования;
  • наследование / полиморфизм.

Каждый дает свой способ создания определенного пользователем типа, основанного на различных типах условий.

Не зная, чего вы пытаетесь достичь, это лучшее, что я могу сделать.

0 голосов
/ 24 мая 2011

Если это во время компиляции, простая #ifdef или шаблонная специализация отлично подойдет для этой цели.Если это во время выполнения и вам нужна семантика значений, вы можете использовать boost::optional<my_struct_of_optional_members>, и если вы справляетесь со ссылочной семантикой, наследование решит проблему под рукой.

Объединение и тому подобноеподвох не нужен.

0 голосов
/ 24 мая 2011

вставьте union в вашу структуру и используйте флаг, чтобы указать, какая часть объединения является действительной.

enum struct_type
{
    cool,
    fine,
    bad
};

struct demo
{
    struct_type type;
    union
    {
        struct
        {
            double cool_factor;
        } cool_part;
        struct
        {
            int fineness;
        } fine_part;
        struct
        {
            char *bad_stuff;
        } bad_part;
    };
    struct
    {
        int life_is_cool;
    } common_part;
};
0 голосов
/ 24 мая 2011

Чистый и простой ответ C ++: использовать классы.

Я не могу определить по вашему вопросу, что вы пытаетесь достичь: изменение времени выполнения или изменение времени компиляции, но в любом случае, я сомневаюсь, что вы получите работоспособную реализацию любым другим способом.(Шаблонное метапрограммирование в стороне ... что не для слабонервных.)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...