как динамически создавать методы для работы с объектами класса, инициализированными во время выполнения - PullRequest
1 голос
/ 25 октября 2010

У меня есть класс, скажем

class AddElement{
    int a,b,c;
}

С помощью методов для установки / получения a, b, c ... Мой вопрос определенно является логическим вопросом - скажем, я реализую AddElement следующим образом:

int Value=1;
Value+=AddElement.get_a()+AddElement.get_b()+AddElement.get_b();

Теперь представьте, что я хочу сделать выше, за исключением того, что «a, b, c» теперь являются массивами, и вместо «добавления» я делаю скалярное сложение. Во время выполнения иногда мне нужно 'a', но не 'b' или 'c', поэтому я могу переписать как:

Value+=AddElement.get_a();

(Конечно, + = перегружен для представления скалярного сложения ... и значение того же размера, что и a) - В других случаях мне может понадобиться только b или c для добавления и т. Д. *

Есть ли способ выбрать, какие элементы, a, b, c, я хочу инициализировать и позже использовать во время выполнения? (т.е. я не хочу распределять по массиву огромный массив, если я не собираюсь его использовать).

В конце мне нужен класс, который имеет a, b, c, а затем методы, которые могут работать с любой комбинацией a, b или c - чтобы пользователь определял, какие методы ему нужны во время выполнения (с помощью некоторого флага или файл конфигурации).

В настоящее время я делаю следующее:

Value+=AddElement.get_a()*FlagA+AddElement.get_b()*FlagB+AddElement.get_c()*FlagC;

где FlagA = 1, если вы хотите использовать «a» в добавлении, или 0, если вы не хотите, чтобы оно было включено (то же самое для FlagB и FlagC). Это дорого, если массив 'a' очень большой.

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

Редактировать 2 Я также забыл добавить, что не могу использовать какие-либо условия во время реализации дополнения (это будет использоваться в ядре CUDA, и у меня не может быть никакого расхождения потоков - я надеялся избежать упоминания CUDA, так как это полностью вопрос c ++)

Редактировать 3 Я считаю, что мне нужно использовать виртуальные функции. Я хочу вызывать функцию таким же образом, за исключением того, что она выполняет функцию для конкретного случая.

Редактировать 4 Я был бы признателен, если бы кто-то взглянул на мое решение - может быть, оно слишком «экзотично», и есть более простой метод для достижения той же цели. Спасибо за все предложения!

Редактировать 5 Благодаря другому пользователю я посмотрел на шаблон стратегического дизайна - и это именно то решение, которое я использовал для этой проблемы. Я никогда не слышал об этом раньше и в итоге переосмыслил проблему, которая уже была решена (потребовалось время, чтобы кто-то что-то об этом упомянул). Итак, решение: Определить алгоритм во время выполнения = шаблон стратегического проектирования.

Ответы [ 5 ]

2 голосов
/ 25 октября 2010

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

1 голос
/ 26 октября 2010

Так что я думаю, что понял -

struct S{
    int x,y;
    bool needx,needy;
};

class AnyFunction {
    protected:
        S Vals;
        int TotalValue;
    public:
        virtual void SetValues(void) =0;
        virtual void AddValues(void) =0;
}

class ImplementationFunc1 : public AnyFunction {
    public:
    void SetValues(S * Vals) { S.x=Vals->xval; }
    void AddValues(void){ TotalValue+=Vals->x; }
}

class ImplementationFunc2 : public AnyFunction {
    public:
    void SetValues(S * Vals) {S.x=Vals->xval;S.y=Vals->yval;}
    void AddValues(void){ TotalValue+=(Vals->x+Vals->y); }
}

int main(){
S SVals;
AnyFunction * APointerToAnyFunction;
// read a file that says if we need either x or y
SVals.needx=true; // (i.e. read from file)
SVals.needy=false; // (read from file)

if(Svals.needx){
    SVals.x=Xfromfile;
    if (Svals.needy){
        ImplementationFunc2 Imp1;
        SVals.y=yfromfile;
        APointerToAnyFunction=&Imp1;
    }
    else{
        ImplementationFunc1 Imp2;
        APointerToAnyFunction=&Imp2;
   }
}
...
// blah set some values
...

// So now I can call the function the same way (i.e. the call is always the same, no matter what kind of addition it needs to do), but I have all
// the logic for the conditions done _outside_ the addition
APointerToAnyFunction->AddValues();

Так что это должно в основном делать это! нет, я могу использовать вызов: "APointerToAnyFunction-> AddValues ​​()", чтобы выполнить сложение. Реализация может быть определена с помощью флагов в начале программы, затем я могу написать отдельный класс для каждого условия, которое мне нужно выполнить, и затем мой полиморфный класс наследует свойства базового класса.

Извините, если я не полностью определил свою проблему, или утверждение было расплывчатым - я действительно не знал точно, как сделать то, что объяснял, но знал, что это возможно. Это правильный путь? Есть ли более эффективный способ?

Спасибо всем, кто откликнулся. Конечно, когда x и y являются массивами, я динамически распределяю x и y при необходимости ...

1 голос
/ 25 октября 2010

А что-то вроде этого?

vector<pair<int, bool>> values(3);
values[0].first = 1;
values[0].second = false;

values[1].first = 2;
values[1].second = true;

values[2].first = 3;
values[2].second = false;

int sum = values[0].first * values[0].second + 
          values[1].first * values[1].second + 
          values[2].first * values[2].second;

Возможно, вы могли бы сделать этот очиститель / расширяемый с помощью функторов и <algorithm>.

Мне не понятно, почему условные выражения - это плохо- умножение будет дороже, я думаю.Это ограничение CUDA или особенность?

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

1 голос
/ 25 октября 2010

Этот грубый набросок кода работает для вас?

struct S{
    int getx() {return 0;}
    int gety() {return 0;}
    int getz() {return 0;}
};

int main(){
    int (S::*p[3])(); // allocate as per need
    p[0] = &S::getx;  // populate as per need at run time
    p[1] = &S::gety;
    p[2] = 0;

    int val = 1;
    S obj;

    int nCount = 0;

    while(p[nCount] != 0)
        val += (obj.*(p[nCount++]))();
}

РЕДАКТИРОВАТЬ 2: @Steve Townsend: Это верно.Я пропустил эти условные вещи.

Как насчет этого?

struct S{
    int getx() {return 0;}
    int gety() {return 0;}
    int getz() {return 0;}
    S(){}
    S(S &obj, int (S::*p)()){
        val += (obj.*p)();
    }
    static int val;
};

int S::val = 0;

int main(){
    S obj;
    S buf[] = {S(obj, &S::getx), S(obj, &S::gety)};  // the magic happens here in
                                                      // the constructor
}
0 голосов
/ 25 октября 2010

Как насчет std::vector элементов?

Спецификация проблемы немного неясна, если не сказать больше, но я думаю, что будет работать для вас.

Приветствия & hth.,

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...