Назначение указателей функций C++ функциям-членам одного и того же объекта

Как мне заставить работать назначения указателя функции (и, возможно, остальные) в test.calculate?

#include <iostream>

class test {

    int a;
    int b;

    int add (){
        return a + b;
    }

    int multiply (){
        return a*b;
    }

    public:
    int calculate (char operatr, int operand1, int operand2){
        int (*opPtr)() = NULL;

        a = operand1;
        b = operand2;

        if (operatr == '+')
            opPtr = this.*add;
        if (operatr == '*')
            opPtr = this.*multiply;

        return opPtr();
    }
};

int main(){
    test t;
    std::cout << t.calculate ('+', 2, 3);
}

person toochin    schedule 01.02.2011    source источник


Ответы (2)


Есть несколько проблем с вашим кодом.

Во-первых, int (*opPtr)() = NULL; не является указателем на функцию-член, это указатель на свободную функцию. Объявите указатель на функцию-член следующим образом:

int (test::*opPtr)() = NULL;

Во-вторых, вам нужно указать область класса при получении адреса функции-члена, например:

if (operatr == '+') opPtr = &test::add;
if (operatr == '*') opPtr = &test::multiply;

Наконец, для вызова через указатель функции-члена существует специальный синтаксис:

return (this->*opPtr)();

Вот полный рабочий пример:

#include <iostream>

class test {

    int a;
    int b;

    int add (){
        return a + b;
    }

    int multiply (){
        return a*b;
    }

    public:
    int calculate (char operatr, int operand1, int operand2){
        int (test::*opPtr)() = NULL;

        a = operand1;
        b = operand2;

        if (operatr == '+') opPtr = &test::add;
        if (operatr == '*') opPtr = &test::multiply;

        return (this->*opPtr)();
    }
};

int main(){
    test t;
    std::cout << t.calculate ('+', 2, 3);
}
person John Dibling    schedule 01.02.2011
comment
Спасибо, вы просто спасли мой день. - person toochin; 01.02.2011
comment
@PeterMortensen: Не будь этим парнем. Никто не любит этого парня. - person John Dibling; 03.11.2013

Вот так int (test::*opPtr)() = NULL;. См. http://www.parashift.com/c++-faq-lite/pointers-to-members.html#faq-33.1

Изменить: также используйте if (operatr == '+') opPtr = &test::add; вместо [..] = this.add и return (this->(opPtr))(); вместо return opPtr();. Фактически, используйте определения типов и макросы, как говорится в FAQ, и, возможно, параметры функций-членов вместо членов класса a и b.

person LumpN    schedule 01.02.2011
comment
Верно, но проблем больше, чем только эта. - person John Dibling; 01.02.2011