Форум программистов, компьютерный форум CyberForum.ru
Наши страницы

С++ для начинающих

Войти
Регистрация
Восстановить пароль
 
 
scriptus
1 / 1 / 0
Регистрация: 08.02.2012
Сообщений: 16
#1

"Двойной" доступ к переменным класса - C++

29.11.2012, 17:40. Просмотров 801. Ответов 17
Метки нет (Все метки)

Господа, прошу совета в изложенной ниже ситуации. Часто мне встречается в различных вариациях, поэтому есть потребность в изящном решении. Итак, есть, допустим, такой класс:

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class EnumerousVariables
{
public:
    EnumerousVariables();
    ~EnumerousVariables();
 
    TypeA&  getA() const;
    TypeB&  getB() const;
    // ...
    TypeZZ& getZZ() const;
 
    UniformType& operator [] (int i) const;
 
private:
    Type A a;
    TypeB b;
    // ...
    TypeZZ zz;
};
Класс содержит много переменных разных типов с соответствующими методами доступа к ним. Хочется реализовать метод доступа по индексу (нужен для внешнего модуля), причем все переменные должны конвертироваться к одному типу UniformType. Последний представляет из себя примерно следующее:

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class UniformType
{
public:
    UniformType()
    UniformType(const TypeA& _a);
    UniformType(const TypeB& _b);
    // ...
    UniformType(const TypeZZ& _zz);
 
    ~UniformType();
 
    TypeA&  toTypeA(bool& isOK) const;
    TypeB&  toTypeB(bool& isOK) const;
    // ...
    TypeZZ& toTypeZZ(bool& isOK) const;
};
Будем считать, что порядок следования переменных по индексу определен. В данном примере, допустим, алфавитный. Т.е. хочется иметь следующее:

C++
1
2
3
4
5
EnumerousVariables foo = EnumerousVariables();
// где:
// foo[0] == UniformType(foo.getA())
// foo[1] == UniformType(foo.getB())
// и т.д.
Вопрос заключается в следующем. Как реализовать оператор [], не держа копий переменных и не используя switch-case?
В голову приходит только один вариант - изначально держать данные в виде контейнера переменных типа UniformType, а в соответсвующих get-ах set-ах конвертировать данные к(из) соответствующему типу, но это как-то не айс.

Заранее спасибо.
1
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
29.11.2012, 17:40
Здравствуйте! Я подобрал для вас темы с ответами на вопрос "Двойной" доступ к переменным класса (C++):

Доступ из вложенного класса к членам "родителя" - C++
Доброго времени суток. Есть такой класс: class XML { protected: int root; public: class reader ...

В зависимости от времени года "весна", "лето", "осень", "зима" определить погоду "тепло", "жарко", "холодно", "очень холодно" - C++
В зависимости от времени года "весна", "лето", "осень", "зима" определить погоду "тепло", "жарко", "холодно", "очень холодно". Я так...

Объяснить что такое "раздельная компиляция", что такое "интерфейс класса" и "реализация класса" на примере - C++
Есть класс, содержащий объекты и конструктор. Конструктор объявляется в одном из cpp файлов(их несколько). Можно ли, как-то, использовать...

Реализация класса "Студент" и наследование от него класса "Аспирант" - C++
Помогите, пожалуйста! Создать абстрактный базовый класс Person, описывающий обычного человека. Создайте производный класс Student,...

Доступ к переменным класса - C++
Давным давно помню была такая фишка в сях, когда приходилось много раз писать конструкцию типа "VarName->member()" можно было заключить это...

Ошибки "Expression syntax" и "Unreachable code" при реализации класса матриц - C++
Подскажите по коду. #include <iostream.h> #include <math.h> #include <string.h> #include <stdio.h> #include <windows.h> ...

17
Kastaneda
Форумчанин
Эксперт С++
4655 / 2863 / 228
Регистрация: 12.12.2009
Сообщений: 7,275
Записей в блоге: 2
Завершенные тесты: 1
29.11.2012, 18:27 #2
Может массив указателей? Размер указателя - величина постоянная и от типа не зависит. Ну а в operator[] сделать просто
C++
1
return *(ptrArray[i]);
0
scriptus
1 / 1 / 0
Регистрация: 08.02.2012
Сообщений: 16
30.11.2012, 12:59  [ТС] #3
Тоже думал уже.
Получается тогда так:
C++
1
return UniformType(*(ptrArray[i]))
Но для корректного разыменовывания указателя нужно знать тип переменной (чтобы UniformType понимал, чего ему кормят).
А тип переменной-указателя мы как раз и потеряем при записи его в ptrArray. Т.е. перед разыменовыванием указателя нужно будет сделать cast к соответствующем типу, а тип-то мы и не знаем...

UPD: Добавить в UniformType конструктор UniformType(void*) тоже не вариант, т.к. внутри реализации он все равно должен помнить тип переменной для корректной обратной конвертации.
0
I.M.
564 / 547 / 5
Регистрация: 16.12.2011
Сообщений: 1,389
30.11.2012, 13:18 #4
А почему бы метод
C++
1
TypeA&  getA() const;
не переписать как
C++
1
2
3
4
UniformType&  getA() const
{
   return UniformType(_a);
}
конструктор же определен для типа TypeA
UniformType можно вообще шаблонным классом сделать
0
dederkay
34 / 34 / 0
Регистрация: 08.12.2010
Сообщений: 161
30.11.2012, 13:31 #5
как то читал о "двойной передаче" где компилятор определял какой тип при помощи операторов, и я думаю
Джеф Элдер прекрасно описал данный способ в С++ Библиотека Программиста. Где все возлагается на операторы. Но придется делать абстрактный базовый, и при большом количестве типов будет много операторов, оочень много операторов.
0
scriptus
1 / 1 / 0
Регистрация: 08.02.2012
Сообщений: 16
30.11.2012, 13:36  [ТС] #6
I.M., согласен, решение проблемы, тоже рассматривалось.
Только методов
C++
1
2
TypeA& getA() const;
// и т.д.
это не отменяет, они нужны.
Тогда возникает компромисс - или вдвое увеличивается количество методов, или потом где мне нужен "родной" тип делать
C++
1
TypeA aa = foo.getA().toTypeA()
чего о-о-очень не хотелось бы делать.


dederkay, спасибо, почитаю на досуге. Правда, здесь это едва будет уместно - не такая уж и глобальная проблема в конце концов Можно и switch'ами обойтись, но уж больно не хочется
0
dederkay
34 / 34 / 0
Регистрация: 08.12.2010
Сообщений: 161
02.12.2012, 18:42 #7
доброго, меня вот что интересует нельзя ли использовать
C++
1
auto
который с срр11 для данного случая? Если выйдет можете отписаться?!
0
I.M.
564 / 547 / 5
Регистрация: 16.12.2011
Сообщений: 1,389
02.12.2012, 19:36 #8
dederkay, "для данного случая" - для какого? auto позволяет программисту не писать длинные типы данных, но auto заменяется на них во время компиляции. Иначе говоря типы должны быть известны во время компиляции.
0
dederkay
34 / 34 / 0
Регистрация: 08.12.2010
Сообщений: 161
02.12.2012, 21:39 #9
да вы правы, тут ведь внешний модуль, как то не досмотрел, извините. Да прочитал This type is easily determined procedurally by the compiler as part of its semantic analysis duties. Тупанул(
0
I.M.
564 / 547 / 5
Регистрация: 16.12.2011
Сообщений: 1,389
02.12.2012, 22:09 #10
scriptus, а как вообще вся эта система должна работать?
представим, что у вас есть клевый get метод в виде оператора [], возвращающий нужное поле с данными в виде класса UniformType.
Что дальше?
как вы хотите дальше работать с этим классом? как вы узнаете, что за тип данных внутри?
0
scriptus
1 / 1 / 0
Регистрация: 08.02.2012
Сообщений: 16
03.12.2012, 11:39  [ТС] #11
I.M., конкретно сейчас все эти танцы нужны для third-party модуля, который понимает входные данные только в формате UniformType. Модуль закрытый и все что мне доступно - конструкторы UniformType для классов, с которыми работает система в целом (а их много). "Родные" же типы данных нужны для корректной работы моей части системы.
Вообще изначально это проблема плохой проработки интерфейса стороннего модуля (имхо).

Другой пример (навскидку) из Qt - класс QAbstractItemModel (и наследуемые от него) - модель данных для qt'шной парадигмы Model-View (разновидность классической MVC). Там есть такая штука:
C++ (Qt)
1
virtual QVariant data (const QModelIndex & index, int role = Qt::DisplayRole ) const = 0;
которая по индексу возвращает данные типа QVariant (аналог UniformType в приведенном выше примере). Этот метод нужно реализовать в наследуемом классе, что в принципе приводит к аналогичному вопросу.
В Qt же такой интерфейс используется для взаимодействия с виджетами (QListView, QTableView и т.п.) для отображения данных модели.

Добавлено через 33 минуты
Сорри, не ответил на вопрос. Дальше с преобразованным типом работает сторонний модуль, как и что там - хз. Судя по доступному заголовочнику могу предположить, что UniformType нужен для корректного хранения данных в некоторой специфичной железке. Как конвертируется назад - тоже загадка. Все, что я могу сделать - а) построить UnifromType из поддерживаемого им типа данных, б) конвертнуть назад в любой другой поддерживаемый тип и посмотреть на bool& ok. Есть подозрение, что в конструкторе просто проставляется определенный флаг, который запоминает исходный тип данных и в дальнейшем определяет, во что можно конвертировать UniformType обратно.
0
Deviaphan
Делаю внезапно и красиво
Эксперт С++
1305 / 1220 / 50
Регистрация: 22.03.2011
Сообщений: 3,744
03.12.2012, 13:09 #12
boost.variant или полиморфизм.
0
I.M.
564 / 547 / 5
Регистрация: 16.12.2011
Сообщений: 1,389
03.12.2012, 13:12 #13
scriptus, т.е. насколько я понимаю, менять класс UniformType нельзя? но гарантируется, что в нем есть все нужные конструкторы для ваших типов?
0
scriptus
1 / 1 / 0
Регистрация: 08.02.2012
Сообщений: 16
03.12.2012, 17:04  [ТС] #14
Deviaphan, думал. Не вижу существенных преимуществ, ибо уже есть UniformType, обладающий в этом конкретном случае схожим функционалом. Имхо, только геморрой приобретается, т.к. компилятор в этом случае не выполняет проверку типа при обратном преобразовании. Это я про boost::variant.
Может, я что-то не понимаю и Вы объясните свою позицию чуть подробнее?

I.M., верно. И первое, и второе.
0
Deviaphan
Делаю внезапно и красиво
Эксперт С++
1305 / 1220 / 50
Регистрация: 22.03.2011
Сообщений: 3,744
03.12.2012, 17:43 #15
Аргументирую: ты хочешь реализовать переключение типов, а в ООП переключение типов - зло. буст.вариант лучше тем, что его сотни тысяч раз использовали и отлаживали.
Вопрос в другом: зачем тебе индексированный доступ к объектам РАЗНОГО типа. Ты не сможешь работать с ними в цикле, значит, тебе не нужен индексированный доступ. Если же ты хочешь однообразно работать с ними в цикле, то у них должен быть общий предок и решение твоей проблемы - полиморфизм.
0
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
03.12.2012, 17:43
Привет! Вот еще темы с ответами:

Создание объекта класса сразу после его описания (между "}" и ";") - C++
Пишу проект с дюжиной хедеров и десятком cpp-шников. Мне нужны пара объектов класса А, которые должны существовать на протяжении всей...

Для класса "Футболист" создать производный класс "Нападающий" - C++
помогите плиз написать главную функцию и внешний метод и посмотрите ошибки класс ФУТБОЛИСТ с атрибутами: фамилия, название команды,...

Ошибка экземпляра класса: отсутствие ";" перед идентификатором "o_scenes_1" - C++
В программе есть два класса, для каждого создано по одному экземпляру. Почему-то в месте создания каждого из экземпляров выдает ошибку: ...

Разработать класс "Массив больших чисел", который состоит из объектов класса "Большие целые числа". Найти сумму элементов массива. - C++
Разработать класс "Массив больших чисел", который состоит из объектов класса "Большие целые числа". Найти сумму элементов массива. ...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
15
Yandex
Объявления
03.12.2012, 17:43
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2017, vBulletin Solutions, Inc.
Рейтинг@Mail.ru