Инициализация аггрегируемого объекта
От: Аноним  
Дата: 23.09.04 04:24
Оценка:
Добрый день!

Пусть есть код:
class A
{
public:
  A();
  ~A();

  void SetId( int _id) { id = _id; };

private:
  int id;
};

class B
{
public:
  B();
  ~B();

  A a1, a2, ... , aN;

};

Теперь при создании экземпляров класса B необходимо проинициализировать аггрегируемые им объекты a1, a2, ... , aN.
Сейчас просто напрямую обращаюсь к этим объектам т.к. они public
B b1, b2;
b1.a1.SetId(1);
b1.a2.SetId(8);
//............
b1.aN.SetId(5);

b2.a1.SetId(11);
b2.a2.SetId(4);
//............
b2.aN.SetId(9);

Но такой подход как-то не вписывается в концепцию инкапсуляции и по-хорошему объекты a1, a2, ... , aN надо выносить в private область. Тем более что дальше они используются только в контексте класса B.
Вопрос: как это сделать красиво и эффективно?

Первое что приходит в голову это передавать структуру с данными инициализации
typedef struct
{
  int a1, a2, ... , aN;
} INIT_PARAM;

class B
{
public:
  B();
  ~B();

  void InitA( INIT_PARAM *pPar)
  {
    a1.SetId( pPar->a1);
    // ...........
  };
private:
  A a1, a2, ... , aN;
};

ну и соот-но использовать
INIT_PARAM par;
B b1, b2;
par.a1 = 1;
// ......
b1.InitA(par);

par.a1 = 11;
// ......
b2.InitA(par);

Но в этом случае мы получаем дополнительное расбухание кода и накладные расходы по инициализации.

Наверняка проблема уже сто раз поднималась и хотелось бы знать как ее решаете Вы?
Re: Инициализация аггрегируемого объекта
От: Аноним  
Дата: 23.09.04 04:40
Оценка:
Попробуй использовать функцию с неуказанным кол-вом параметров
Re[2]: Инициализация аггрегируемого объекта
От: Аноним  
Дата: 23.09.04 05:06
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Попробуй использовать функцию с неуказанным кол-вом параметров


т.е
void InitA( int nParam, .../* и тут значения id для всех a1 ... aN*/);

хммм, боюсь что читабельность кода от этого не улучшится (ИМХО). Да и по поводу эффективности большой вопрос.
Re: Инициализация аггрегируемого объекта
От: PM  
Дата: 23.09.04 06:21
Оценка:
Здраствуйте, , Вы писали:
> [code]
> class B
> {
> public:
> B();
> ~B();

> A a1, a2, ... , aN;

> };
> [/ccode]
> Теперь при создании экземпляров класса B необходимо проинициализировать
> аггрегируемые им объекты a1, a2, ... , aN. Сейчас просто напрямую
> обращаюсь к этим объектам т.к. они public
>
> B b1, b2;
> b1.a1.SetId(1);
> b1.a2.SetId(8);
> //............
> b1.aN.SetId(5);

> b2.a1.SetId(11);
> b2.a2.SetId(4);
> //............
> b2.aN.SetId(9);
>

> Но такой подход как-то не вписывается в концепцию инкапсуляции и
> по-хорошему объекты a1, a2, ... , aN надо выносить в private область. Тем
> более что дальше они используются только в контексте класса B. Вопрос:
> как это сделать красиво и эффективно?

А что мешает инициализировать данные в конструкторе B?
B::B()
{
    a1.SetId(1);
    a2.SetId(8);
    // ...
}

> Первое что приходит в голову это передавать структуру с данными инициализации
[код поскипан]
> Но в этом случае мы получаем дополнительное расбухание кода и накладные расходы по инициализации.
Профайлер показал, что на инициализацию экземпляров класса B требуется большое кол-во ресурсов? Если нет, то не стоит усложнять себе жизнь.
foobar2000 v0.8.2: выключен.
Re[2]: Инициализация аггрегируемого объекта
От: Аноним  
Дата: 23.09.04 06:34
Оценка:
Здравствуйте, PM, Вы писали:

PM>А что мешает инициализировать данные в конструкторе B?

Дело в том, что класс B не располагает данными для инициализации объектов a1 .... aN. Он должен получать их извне.

PM>Профайлер показал, что на инициализацию экземпляров класса B требуется большое кол-во ресурсов? Если нет, то не стоит усложнять себе жизнь.

Да нет, ресурсы не большие. Вопрос вобщем то был, а существуют ли какие-то общепринятые варианты решения этой задачи.
Re[3]: Инициализация аггрегируемого объекта
От: PM  
Дата: 23.09.04 06:50
Оценка:
Здраствуйте, , Вы писали:

> Здравствуйте, PM, Вы писали:


PM>> А что мешает инициализировать данные в конструкторе B?

> Дело в том, что класс B не располагает данными для инициализации объектов
> a1 .... aN. Он должен получать их извне.

B::B(int id1, int id2, int id3)
{
    a1.SetId(id1);
    a2.SetId(id2);
    a3.SetId(id3);
}


PM>> Профайлер показал, что на инициализацию экземпляров класса B требуется

PM>> большое кол-во ресурсов? Если нет, то не стоит усложнять себе жизнь.
> Да нет, ресурсы не большие. Вопрос вобщем то был, а существуют ли
> какие-то общепринятые варианты решения этой задачи.
Использовать дополнительный объект, в котором передается нужная информация, как Вы это написали в первом сообщении
foobar2000 v0.8.2: выключен.
Re: Инициализация аггрегируемого объекта
От: sadomovalex Россия http://sadomovalex.blogspot.com
Дата: 23.09.04 06:51
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Но в этом случае мы получаем дополнительное расбухание кода и накладные расходы по инициализации.


А>Наверняка проблема уже сто раз поднималась и хотелось бы знать как ее решаете Вы?


Храни объекты A в векторе, тогда проинициализировать можно так:

void B::init(const vector<A> &a)
{
   m_a.assign(a.begin(), a.end());
}
"Что не завершено, не сделано вовсе" Гаусс
Re[2]: Инициализация аггрегируемого объекта
От: misha_sk Россия  
Дата: 23.09.04 10:54
Оценка:
Здравствуйте, sadomovalex, Вы писали:

S>Здравствуйте, Аноним, Вы писали:


А>>Но в этом случае мы получаем дополнительное расбухание кода и накладные расходы по инициализации.


А>>Наверняка проблема уже сто раз поднималась и хотелось бы знать как ее решаете Вы?


S>Храни объекты A в векторе, тогда проинициализировать можно так:


S>
S>void B::init(const vector<A> &a)
S>{
S>   m_a.assign(a.begin(), a.end());
S>}
S>


А лучше так:

template<typename In>
void B::init(In first, In last)
{
    m_a.assign(first, last);
}
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.