2016-06-08 8 views
-6

Представьте, что вы есть класс с 100 или более переменных членов:Как передать membervariable как переменная сама

class DataContainer { int a1; int a2; ... double a100; }; 

и другой класс, который обращается и запчастями к нему анализ переменных в первом классе:

class Analysis { 
    protected: 
    DataContainer *myData; 
    void myVar1, myVar2; 

    public: 
    Analysis() {...} 
    void myChoice(void a, void b) { myVar1 = a; myVar2 = b } 
    void Analyse(DataContainer data) { 
    myData = data; 
    /* do something with myVar1 and myVar2 */ 
    } 
}; 

, но перед анализом вы должны выбрать, какие параметры использовать. Я хотел бы знать, как написать призыв к этой функции myChoice, которая не просто передает содержимое переменной, а выбор самого membervariable.

Чтобы узнать больше: я считаю, что позиция в памяти элемента класса относительно самого класса фиксирована (это?). Независимо, если это новый экземпляр этого класса или нет. Итак, как я могу сообщить комбайтору «Пожалуйста, используйте membervariable a3 always». Вместо содержания a3.

+5

Переменные '100' участника? Ты шутишь, что ли? Что случилось с использованием массивов? – WhiZTiM

+0

Моя основная программа намного сложнее, я старался упростить этот пример. Это общая структура данных с различным типом данных, поэтому нет массивов .... :-( – Georg

+1

Очень плохо, если попытаться получить доступ к переменным-членам через указатель на класс. Есть небольшая вещь, называемая заполнением, которая будет встаньте на свой путь. – NathanOliver

ответ

1

Это именно то, для чего нужны pointers-to-data-members.

int DataContainer::* myVar1 = &DataContainer::a1; 
double DataContainer::* myVar2 = &DataContainer::a100; 

Я думаю, что положение в памяти класса-члена относительно класса сама фиксирована (это?)

Это действительно. Относительная позиция не изменяется во время выполнения. Вот почему работают указатели на данные. Они могут быть реализованы как смещение памяти.

PS. Учитывая, насколько массивным является DataContainer, я бы не рекомендовал передавать его по значению, если вы можете его избежать.

PPS. Рассмотрим группировку переменных-членов в подструктуры.

+0

hm .... Я так не думаю ... Изображение после «выбора» экземпляр класса удаляется, а затем передается новый для анализа, указатели будут отличаться – Georg

+0

нормально, это значит для моего случая , что я могу просто вычислить (size_t (originalClass) - size_t (& selectedMember) + size_t (newClassInstance)), чтобы найти указатель на этот член в новом классе – Georg

+0

извините наоборот «класс-класс + класс» – Georg

0

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

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

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

class Analysis { 
public: 
    virtual void Analyze(const DataContainer &data) = 0; 
    virtual ~Analysis(); 
protected: 
    void special_computation(int x, int y, double z); 
}; 

class SpecificKindOfAnalysis : public Analysis { 
public: 
    void Analyze(const DataContainer &data){ 
     int x = data.a27; 
     int y = data.a12; 
     double z = data.a99; 
     special_computation(x,y,z); 
    } 
}; 

Это на самом деле выглядит довольно ужасно с именами переменных, таких как х = data.a27, но я предполагаю, что мы пытаемся быть вообще здесь, и реальная программа имеет значимые имена.