2013-05-14 3 views
-1

Я ищу для моделирования с очень сложными начальными условиями от пользователя. Я пишу class A, чьи переменные-члены должны быть инициализированы пользователем перед запуском A.Solve(), чтобы получить результаты, хранящиеся в файле. Инициализация довольно сложная и требует нескольких временных структур данных, которые больше не понадобятся после инициализации. Итак, я написал еще один класс под названием class Initializer, в котором хранится ссылка на объект class A. Мой код будет выглядеть следующим образом:Моделирование класса Дизайн

class A { 
    friend class Initializer; 
    private: 
    // member variables storing the state of the system 
    public: 
    void Solve(); 
    ... 
}; 

class Initializer { 
    private: 
    A& a 
    // Other data structures used in the initialization 
    ... 
    public: 
    // functions called by the user to set up for the initialization 
    ... 
    Initialize(); // after this is called, a will be ready to solve 
}; 

int main(...) { 
    A a; 
    Initializer init(a); 
    // call functions on init to initialize the system 
    ... 
    init.Initialize(); 
    a.Solve(); 
    return 0; 
} 

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

A a; 
    Initializer *init = new Initializer(a); 
    .... 
    init.Initialize(); 
    delete init; 
    a.Solve(); 

Или это выглядит ненужным и я должен просто есть все, содержащиеся в class A?

+1

Я не думаю, что здесь достаточно информации. Это зависит от многих вещей. Единственная причина создания класса «initializer» (с учетом упрощенного контекста вопроса) для этих данных, с моей точки зрения, заключалась бы в том, чтобы сохранить его в том случае, если вам нужно было создать множество версий класса a, поэтому вы может освобождать экземпляры класса a и поддерживать его данные конфигурации.В противном случае мне кажется, что это лишний слой абстракции. Но опять же, это мнение формируется на очень ограниченном объеме информации. – ChrisCM

+0

Я согласен с @ChrisCM. Ненужный слой абстракции, если у вас есть только 1 'A' для инициализации. Что касается освобождения «Инициализатора» после 'init.Initialize()', то динамическое распределение через 'new/delete' будет работать. Вы также можете обернуть инициализацию инициализации (a); ...; init.Initialize() 'в блоке' {} ', или вы можете перемещать инициализатор инициализации (a); ...; init.Initialize() 'в какую-нибудь функцию' doIniti (a) '... –

ответ

1

Чтобы ответить на оригинальную линию мысли, обычное решение ограничить сферу действия переменной init:

A a; 
{ 
    Initializer init(a); 
    //... 
} // init is destroyed as soon as the scope exits 
a.Solve(); 

Ваш new/delete вариант является довольно хрупким и будет утечка памяти, если что-то бросает между new и delete. Чтобы исправить это, используйте смарт-указатели:

A a; 
std::unique_ptr<Initializer> init(new Initializer(a)); 
//... 
init.reset(); 
a.Solve(); 

Однако, как уже говорили другие, вся эта конструкция любопытное странно, и, вероятно, слишком много. Если инициализация действительно настолько сложна, что вы не можете уйти с конструкторами, тогда вы можете сделать это наоборот: вместо Initializer, принимая аргумент A и действуя на нем, вы должны передать полностью готовый к использованию Initializer - A, который в свою очередь либо скопирует все Initializer, чтобы сохранить копию данных, либо просто скопировать соответствующие биты. Initializer следует, вероятно, переименовать в Config или что-то в этом роде. Обратите внимание, что теперь объект Config/Initializer можно повторно использовать для инициализации нескольких объектов A и даже может быть изменен между двумя инициализациями A.

К сожалению, это трудно дать вам окончательный совет с такой небольшой информацией.

Примечание: Если вы используете C++ 11, вас может заинтересовать std::initializer_list, который позволяет использовать новый синтаксис синтаксиса. В зависимости от сложности ваших данных это может потребовать больше работы, чем ваше текущее решение, но в итоге вы получите очень красивый и интуитивно понятный синтаксис.

0

Здесь, используя другой класс для целей инициализации, кажется, излишним.

Просто инициализируйте конструктор класса A. После завершения выполнения конструктора временные структуры данных будут освобождены автоматически.

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