Можно ли получить доступ к члену объекта класса из объекта др. класса

Тема в разделе "Общие вопросы по С и С++", создана пользователем Monarh, 26 авг 2009.

  1. Monarh

    Monarh Active Member

    Регистрация:
    14 фев 2009
    Сообщения:
    34
    Симпатии:
    0
    Здравствуйте.
    Подскажите пожалуйста можно ли получить доступ к члену объекта класса из объекта другого класса ?
    На примере:
    Есть класс Cls_Area с приватным членом DimensionSpace - Размерность_Пространства,
    а также массивом объектов другого класса Cls_Point.
    Код (Text):
    class Cls_Area
    {
    private:
    const unsigned int DimensionSpace;
    Cls_Point ClsA_Points[ 27 000 000 ];
    ...
    };
    Размерность_Пространства у любого Объекта класса Cls_Area может быть произвольная.

    Объекты класса Cls_Point принадлежащие объекту класса Cls_Area имеют ту же Размерность_Пространства, что и объект класса Cls_Area.

    Можно ли не хранить внутри каждого объекта класса Cls_Point параметр - DimensionSpace, а каким-нибудь образом обращаться к
    объекту класса Cls_Area и узнавать у него значение DimensionSpace ?

    Статической её не сделаешь, поскольку у разных объектов может быть разное значение DimensionSpace.
    Передавать ссылку из объекта класса Cls_Area на себя объекту класса Cls_Point, не подходит,
    поскольку тогда нет возможности использовать операторы класса Cls_Point.
    Делать таблицу соответствия между объектами класса Cls_Area и Cls_Point ещё хуже чем хранить константу внутри объекта класса Cls_Point.

    Может кто знает, есть ли какой-нибуть выход из этого ?

    Заранее всем большое спасибо.
     
  2. grigsoft

    grigsoft Well-Known Member

    Регистрация:
    15 ноя 2005
    Сообщения:
    735
    Симпатии:
    0
    А цель конечная какая? Уменьшить размер Cls_Point? Или время на инициализацию массива? очевидный ход - просто передавать размерность внутрь, когда она будет нужна - доп. параметром в вызове методов.
     
  3. European

    Регистрация:
    4 сен 2006
    Сообщения:
    2.580
    Симпатии:
    0
    Делать общедоступными такие вещи - это прямой путь к бардаку в проект
    grigsoft прав, какой смысл?
    И еще, зачем точке знать размерность пространства? Вы уверены в правильности подхода к проектированию?
     
  4. Monarh

    Monarh Active Member

    Регистрация:
    14 фев 2009
    Сообщения:
    34
    Симпатии:
    0
    Цель - Уменьшить размер Cls_Point и как следствие всего массива ClsA_Points_of_Area.
    На самом деле у меня много классов подобных Cls_Point из которых составляются массивы объектов этих классов для каждого объекта класса Cls_Area
    и совсем не хотелось бы нужный только в одном экземпляре параметр DimensionSpace для каждого объекта класса Cls_Area хранить в таком большом количестве копий.

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

    А если передавать этот параметр в методы класса Cls_Point, то нет возможности использовать операторы данного класса,
    поскольку операторы одно- или двух- параметрические, например:
    Код (Text):
    ostream& operator << ( ostream& , Cls_Point& ){...}
    А внутри надо знать количество измерений, чтобы знать сколько выводить.

    Или может я ошибаюсь и внутрь операторов можно передавать дополнительные переменные ?
    Если нет, то как ещё можно решить эту задачу ?

    Да, ошибся, DimensionSpace - приватный член класса Cls_Area. Подредактировал.

    Точка - объект этого пространства.
    И соответственно методы, которые работают с точкой области, то есть методы которые реализованы внутри класса Cls_Point,
    должны знать в каком пространстве данная точка обитает, чтобы работать со всеми её пространственными координатами.

    Заранее всем большое спасибо.
     
  5. grigsoft

    grigsoft Well-Known Member

    Регистрация:
    15 ноя 2005
    Сообщения:
    735
    Симпатии:
    0
    Так а внутренняя логика точки не зависит от пространства? Как то слабо себе представляю. Можно, к примеру, привести код того operator <<? Или там внутри массив координат размером на все случаи? Так может не там надо начинать оптимизировать?

    1. Можно вместо
    Код (Text):
    point >> stream
    писать
    Код (Text):
    point.Output(stream, dimension);
    Криво, но оптимизация требует жертв.
    2. Сколько вариантов размерности в работе? Может проще для каждой размерности - свой класс точек, со статическим членом - размерностью? И аллокатором типа
    Код (Text):
    CPointFactory::CreateArray(dim, size);

    Кстати, а на этапе компиляции все размерности уже известны? Тогда можно было б просто темплейтами сделать.
     
  6. European

    Регистрация:
    4 сен 2006
    Сообщения:
    2.580
    Симпатии:
    0
    Как вариант, можно для хранения вектор использовать и запрашивать размерность у него.
    Приведите конкретный пример, зачем точке знать о пространстве, в котором она работает. Все пространственные координаты должны хранится внутри класса точки, а не в классе пространства
     
  7. Monarh

    Monarh Active Member

    Регистрация:
    14 фев 2009
    Сообщения:
    34
    Симпатии:
    0
    Это вопрос или утверждение ?
    Вроде стоит вопрос, но я выше как раз писал:
    Для примера можно рассмотреть человека - он в каком пространстве обитает ?
    Если это реальный человек - то трёхмерное пространство,
    соответственно он может( методы данного объекта - человек трёхмерный :)) передвигаться вперёд, назад, влево, вправо, прыгать вверх и вниз.
    Если это рисованый человечек - то двухмерное пространство,
    соответственно он может( методы данного объекта - человек двухмерный ;)) передвигаться вперёд, назад, влево, вправо.
    Аналогично и с точкой.

    Если я правильно понял, то именно так - на все случаи.
    То есть:
    Код (Text):
    class Cls_Point
    {
    private:
    typedef double Value_Type;
    typedef Value_Type& Reference;
    Value_Type* DA_Coordinate_Endwise;
    ...
    public:
    Cls_Point( const unsigned int& DimensionSpace );
    Reference operator[] ( const unsigned int& Num_of_Axis );
    friend ostream& operator << ( ostream& , Cls_Point& );
    ...
    };
    Конструктор по соответствующему параметру - DimensionSpace динамически Выделяет_Память( оператором new ) для точки области.
    Код (Text):
    ostream& operator << ( ostream& , Cls_Point& )
    {
    ...
    for( unsigned int UI_Num_of_Axis; UI_Num_of_Axis < DimensionSpace; UI_Num_of_Axis++ )
    cout << DA_Coordinate_Endwise[ UI_Num_of_Axis ] << '\n';
    cout << endl;
    ...
    }
    Если взять Оператор_Присваивания( operator = ), то там тоже будет цикл по пространственным координатам.
    И так во многих операторах.

    А где можно ещё оптимизировать ?
    Да и в общем-то дело не в оптимизации, а в принципиальной ненужности, с точки зрения логики, хранения стольких копий одного параметра.
    Ну и уже во вторую очередь - опять же необоснованный расход Оперативной_Памяти.

    Это тогда от всех операторов придётся отказаться - не выход.

    Вариантов размерности - счётное множество :)
    1,2,3, ... +infinity

    Как вариант, в принципе можно было бы, но НЕ раньше, чем будет реализована поддержка export'а в g++,
    а то придётся все cpp-файлы реализаций классов которые участвуют в образовании области и самой области
    впихивать в h-файлы с определением этих классов, а это не есть good или по-русски сердце не радуется при виде такого бардака :))
    Хотя, наверное нет - это не выход, данные об областях могут и из файла читаться.

    Вектор чего ?
    В классе Точка использовать вектор размерностей ?
    Но это не только хранение самой размерности, от которой я как раз хочу избавиться, но и хранение ещё кучи всего ненужного.

    пространственные координаты - ДА, должны хранится внутри класса точки.
    Но Размерность_Пространства - параметр пространства, а все точки принадлежащие данному пространству,
    по умолчанию должны иметь ту же Размерность_Пространства, что и пространство которому они принадлежат.
    Точки трёхмерного пространства не могут быть двухмерные, иначе они просто будут из другого пространства,
    а соответственно зачем хранить параметр Размерность_Пространства у каждой точки, если этот параметр должен быть единым
    для всех точек данного пространства( Области ).
    Но при этом области могут рассматриваться разной размерности.

    Заранее всем большое спасибо.
     
  8. European

    Регистрация:
    4 сен 2006
    Сообщения:
    2.580
    Симпатии:
    0
    Нет, в классе Cls_Area храните вектор ClsA_Points. Хотя многое зависит от кода его заполнения.

    Далее, по поводу точек и пространства. Что мешает вам передать размерность в конструктор точки и соответствующим образом инициализировать члены класса? Те члены, которые для некоторой размерности не нужны будут инициализироваться некоторой константой.

    Затем, если размерностей может быть 2-3, почему бы не выделить интерфейс для точки и сделать реализации для каждой размерности пространства?
     
  9. grigsoft

    grigsoft Well-Known Member

    Регистрация:
    15 ноя 2005
    Сообщения:
    735
    Симпатии:
    0
    European, так о том и речь - класс Точка тут универсальный, для всех размерностей. Цель - не хранить в точке размерность, потому как точек много. Даже если сделать вектор - в нем самом все равно будет выделено место под размер. И любой указатель на внешнюю функцию или класс тоже. Тут нужно что-то типа шаблона, такого чтобы CPoint<1> и CPoint<n> были разными классами, да еще и генерились в рантайме. Но я такого не знаю. Но я в шаблонах не силен.
    Так что в голову приходит только упомянутая таблица соответствия. Примерно в такой реализации:
    Есть глобальный менеджер памяти для координат. Area обращается к нему с просьбой выделить память для К точек размерности N. На этой памяти располагаются координаты точек - либо сам Area их распределяет, либо Менеджер возвращает объект, который передается в конструктор точки.
    В итоге в точке - только указатель на координаты (DA_Coordinate_Endwise). При необходимости точка обращается к Менеджеру с вопросом - а какой размерности мои координаты по этому адресу? Менеджер может ответить на этот вопрос - по промежутку\хипу, в который попадает адрес. Хотя и потратит O(количество Area в работе). Но тут всегда - или память, или скорость.

    PS. Хотя я бы отказался от операторов. Больше возни с кодом, но не теряем ни памяти, ни скорости.
     
  10. European

    Регистрация:
    4 сен 2006
    Сообщения:
    2.580
    Симпатии:
    0
    Да, действительно... Массив же в Cls_Area, а не в ClsA_Points. Так что совет с вектором не удачен. А все от того, что первый код в теме, это не код класса, который нужно оптимизировать ;)
     
  11. Monarh

    Monarh Active Member

    Регистрация:
    14 фев 2009
    Сообщения:
    34
    Симпатии:
    0
    По-моему это, в данном случае, самый подходящий вариант.

    У меня не один класс Точка, так что, возможно, в других подклассах класса Cls_Area, где не будет необходимости использовать операторы,
    этот подход будет иметь место.
    Хотя маловероятно.
    Как-то НЕ Красиво это выглядит, передавать в каждый метод Точки информацию о её размерности, да и НЕ Безопасно ;)
    А когда сама Точка узнаёт о своей размерности - это более правильно.

    Огромное СПАСИБО Вам grigsoft и European за советы. :wacko:
     
  12. grigsoft

    grigsoft Well-Known Member

    Регистрация:
    15 ноя 2005
    Сообщения:
    735
    Симпатии:
    0
    Если речь идет о миллионах точек, то даже константные расходы на запрос размерности выльются в "копеечку". Я бы попробовал поставить другой вопрос - должна ли точка быть атомарным классом в такой реализации? Может имеет смысл выделить в класс совокупность точек - так чтобы Cls_Area включал не массив, а объект PointSet который инициализируется количеством точек и размерностью пространства. И все операции с точками сосредоточены именно в нем. А может сам Cls_Area для того и создан? Может здесь имеет смысл отказаться от уровня абстракции ради производительности и чистоты кода?
    Потому как реализация внешней таблицы соответствия с точки зрения ООП куда хуже, чем дополнительный параметр.
     
  13. Monarh

    Monarh Active Member

    Регистрация:
    14 фев 2009
    Сообщения:
    34
    Симпатии:
    0
    Для двумерного пространства речь идет о миллионах точек.
    А для трёхмерного пространства речь идет уже о гароздо бооольшем количестве точек, порядка миллиарда и более, на сколько оперативной памяти хватит :)
    миллиард для 3-х мерного пространства - это всего-то кубик из 1000 точек по каждому измерению :)

    Почти Верно. :)
    Cls_Area хоть и не для того создан.
    Но это входит в его обязанности.
    В общем Cls_Area работает с Точками сам посредством Оператора_Доступа_к_Элементам( или иначе Оператора_Доступа_к_Координатам_Точки ) реализованного в классе Точка ( Cls_Point::eek:perator[] ).
    Код (Text):
    class Cls_Point
    {
    private:
    typedef double Value_Type;
    typedef Value_Type& Reference;
    Value_Type* Coordinate_Endwise;
    ...
    public:
    Reference operator[] ( const unsigned int& Num_of_Axis );
    ...
    };

    Cls_Point::Reference Cls_Point::operator[] ( const unsigned int& ConUI_Num_of_Axis )
    {
    return Coordinate_Endwise[ ConUI_Num_of_Axis ];
    }
    А далее, внутри Cls_Area происходит что-то вроде такого:
    Код (Text):
    for( unsigned int UI_Num_of_Point = 0; UI_Num_of_Point < Count_of_Points; UI_Num_of_Point++)
    for( unsigned int UI_Num_of_Axis = 0; UI_Num_of_Axis < DimensionSpace; UI_Num_of_Axis++)
    Работаем_с_Координатами_каждой_Точки( ClsA_Points[ UI_Num_of_Point ][ UI_Num_of_Axis ] );
    Как показано выше Cls_Area работает с координатами Точки сам, зная свою Размерность_Пространства.
    Но иногда Точке необходимо знать размерность своего пространства. Это будет использоваться редко.
    Ну а если будут случаи, когда неоходимы массовые операции, то можно реализовать функцию, или несколько функций по-необходимости,
    которым будут через параметр передаваться Размерность_Пространства.
    Хотя и в таком случае может не быть надобности в передаче параметра, ведь функция будет обрабатывать точки одной Области( Cls_Area )
    и не важно какой она размерности для всех точек этот параметр будет единым, тобишь узнать придётся только один раз ;)))

    Огромное СПАСИБО grigsoft за ответы и советы. :)
     
  14. RocknRolla

    RocknRolla Гость

    А почему бы не использовать парадигму ООП - наследование=)). Может я что-нибудь не понял, но вроде должно решать ваши проблемы
     
Загрузка...

Поделиться этой страницей