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

Monarh

Active member
14.02.2009
34
0
#1
Здравствуйте.
Подскажите пожалуйста можно ли получить доступ к члену объекта класса из объекта другого класса ?
На примере:
Есть класс Cls_Area с приватным членом DimensionSpace - Размерность_Пространства,
а также массивом объектов другого класса Cls_Point.
Код:
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.

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

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

grigsoft

Well-known member
15.11.2005
735
0
#2
А цель конечная какая? Уменьшить размер Cls_Point? Или время на инициализацию массива? очевидный ход - просто передавать размерность внутрь, когда она будет нужна - доп. параметром в вызове методов.
 
04.09.2006
2 566
3
#3
Есть класс Cls_Area с общедоступным членом DimensionSpace - Размерность_Пространства,
Делать общедоступными такие вещи - это прямой путь к бардаку в проект
Можно ли не хранить внутри каждого объекта класса Cls_Point параметр - DimensionSpace, а каким-нибудь образом обращаться к
объекту класса Cls_Area и узнавать у него значение DimensionSpace ?
grigsoft прав, какой смысл?
И еще, зачем точке знать размерность пространства? Вы уверены в правильности подхода к проектированию?
 

Monarh

Active member
14.02.2009
34
0
#4
А цель конечная какая? Уменьшить размер Cls_Point?
Цель - Уменьшить размер Cls_Point и как следствие всего массива ClsA_Points_of_Area.
На самом деле у меня много классов подобных Cls_Point из которых составляются массивы объектов этих классов для каждого объекта класса Cls_Area
и совсем не хотелось бы нужный только в одном экземпляре параметр DimensionSpace для каждого объекта класса Cls_Area хранить в таком большом количестве копий.

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

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

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

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

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

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

grigsoft

Well-known member
15.11.2005
735
0
#5
Так а внутренняя логика точки не зависит от пространства? Как то слабо себе представляю. Можно, к примеру, привести код того operator <<? Или там внутри массив координат размером на все случаи? Так может не там надо начинать оптимизировать?

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

Кстати, а на этапе компиляции все размерности уже известны? Тогда можно было б просто темплейтами сделать.
 
04.09.2006
2 566
3
#6
Как вариант, можно для хранения вектор использовать и запрашивать размерность у него.
И соответственно методы, которые работают с точкой области, то есть методы которые реализованы внутри класса Cls_Point,
должны знать в каком пространстве данная точка обитает, чтобы работать со всеми её пространственными координатами.
Приведите конкретный пример, зачем точке знать о пространстве, в котором она работает. Все пространственные координаты должны хранится внутри класса точки, а не в классе пространства
 

Monarh

Active member
14.02.2009
34
0
#7
Так а внутренняя логика точки не зависит от пространства?
Это вопрос или утверждение ?
Вроде стоит вопрос, но я выше как раз писал:
Точка - объект этого пространства.
И соответственно методы, которые работают с точкой области, то есть методы которые реализованы внутри класса Cls_Point,
должны знать в каком пространстве данная точка обитает, чтобы работать со всеми её пространственными координатами.
Для примера можно рассмотреть человека - он в каком пространстве обитает ?
Если это реальный человек - то трёхмерное пространство,
соответственно он может( методы данного объекта - человек трёхмерный :)) передвигаться вперёд, назад, влево, вправо, прыгать вверх и вниз.
Если это рисованый человечек - то двухмерное пространство,
соответственно он может( методы данного объекта - человек двухмерный ;)) передвигаться вперёд, назад, влево, вправо.
Аналогично и с точкой.

Как то слабо себе представляю. Можно, к примеру, привести код того operator <<? Или там внутри массив координат размером на все случаи?
Если я правильно понял, то именно так - на все случаи.
То есть:
Код:
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 ) для точки области.
Код:
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. Можно вместо
Код:
point >> stream
писать
Код:
point.Output(stream, dimension);
Криво, но оптимизация требует жертв.
Это тогда от всех операторов придётся отказаться - не выход.

2. Сколько вариантов размерности в работе? Может проще для каждой размерности - свой класс точек, со статическим членом - размерностью? И аллокатором типа
Код:
CPointFactory::CreateArray(dim, size);
Вариантов размерности - счётное множество :)
1,2,3, ... +infinity

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

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

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

Заранее всем большое спасибо.
 
04.09.2006
2 566
3
#8
В классе Точка использовать вектор размерностей ?
Нет, в классе Cls_Area храните вектор ClsA_Points. Хотя многое зависит от кода его заполнения.

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

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

grigsoft

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

PS. Хотя я бы отказался от операторов. Больше возни с кодом, но не теряем ни памяти, ни скорости.
 
04.09.2006
2 566
3
#10
European, так о том и речь - класс Точка тут универсальный, для всех размерностей. Цель - не хранить в точке размерность, потому как точек много. Даже если сделать вектор - в нем самом все равно будет выделено место под размер
Да, действительно... Массив же в Cls_Area, а не в ClsA_Points. Так что совет с вектором не удачен. А все от того, что первый код в теме, это не код класса, который нужно оптимизировать ;)
 

Monarh

Active member
14.02.2009
34
0
#11
Так что в голову приходит только упомянутая таблица соответствия. Примерно в такой реализации:
Есть глобальный менеджер памяти для координат. Area обращается к нему с просьбой выделить память для К точек размерности N. На этой памяти располагаются координаты точек - либо сам Area их распределяет, либо Менеджер возвращает объект, который передается в конструктор точки.
В итоге в точке - только указатель на координаты (DA_Coordinate_Endwise). При необходимости точка обращается к Менеджеру с вопросом - а какой размерности мои координаты по этому адресу? Менеджер может ответить на этот вопрос - по промежутку\хипу, в который попадает адрес. Хотя и потратит O(количество Area в работе). Но тут всегда - или память, или скорость.
По-моему это, в данном случае, самый подходящий вариант.

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

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

grigsoft

Well-known member
15.11.2005
735
0
#12
Если речь идет о миллионах точек, то даже константные расходы на запрос размерности выльются в "копеечку". Я бы попробовал поставить другой вопрос - должна ли точка быть атомарным классом в такой реализации? Может имеет смысл выделить в класс совокупность точек - так чтобы Cls_Area включал не массив, а объект PointSet который инициализируется количеством точек и размерностью пространства. И все операции с точками сосредоточены именно в нем. А может сам Cls_Area для того и создан? Может здесь имеет смысл отказаться от уровня абстракции ради производительности и чистоты кода?
Потому как реализация внешней таблицы соответствия с точки зрения ООП куда хуже, чем дополнительный параметр.
 

Monarh

Active member
14.02.2009
34
0
#13
Если речь идет о миллионах точек, то даже константные расходы на запрос размерности выльются в "копеечку".
Для двумерного пространства речь идет о миллионах точек.
А для трёхмерного пространства речь идет уже о гароздо бооольшем количестве точек, порядка миллиарда и более, на сколько оперативной памяти хватит :)
миллиард для 3-х мерного пространства - это всего-то кубик из 1000 точек по каждому измерению :)

Я бы попробовал поставить другой вопрос - должна ли точка быть атомарным классом в такой реализации? Может имеет смысл выделить в класс совокупность точек - так чтобы Cls_Area включал не массив, а объект PointSet который инициализируется количеством точек и размерностью пространства. И все операции с точками сосредоточены именно в нем. А может сам Cls_Area для того и создан?
Почти Верно. :)
Cls_Area хоть и не для того создан.
Но это входит в его обязанности.
В общем Cls_Area работает с Точками сам посредством Оператора_Доступа_к_Элементам( или иначе Оператора_Доступа_к_Координатам_Точки ) реализованного в классе Точка ( Cls_Point::eek:perator[] ).
Код:
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 происходит что-то вроде такого:
Код:
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 за ответы и советы. :)
 
R

RocknRolla

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