2011-05-23 3 views
2

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

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

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

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

+3

Вы можете это сделать? Это зависит. Каковы ваши дополнительные условия? Определены ли они во время выполнения? Во время компиляции? Как? ... –

+0

Это зависит от того, какие именно условия. –

+1

C++ не является динамически типизированным языком, поэтому вы не можете этого сделать. Может быть, если вы объясните, чего вы пытаетесь достичь, тогда мы могли бы помочь немного больше. –

ответ

1

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

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

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

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

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

Второй трюк использует шаблон состояния (см. 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

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

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

+0

Он уже спрашивает о них. –

+1

-1: Вопрос ОП может быть неопределенным, но это не очень полезный ответ. –

+0

@ Томалак: действительно? Ты можешь сказать? OP говорит о структуре, которая больше похожа на C, чем на C++, на мой нервный нос. –

1

Вы можете взломать вокруг с:

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

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

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

-1

вставьте 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; 
}; 
1

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

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

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

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

0

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

Объединение и такой грязный трюк не требуется.

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