C++ вызов функции из вектора указателей функций внутри класса, где определение функции находится в основном

хорошо, в основном у меня есть:

void somefunction();
int main()
{
    //bla bla bla
    SomeClass myclass = SomeClass();
    void(*pointerfunc)() = somefunction;
    myclass.addThingy(pointerfunc);

    //then later i do
    myclass.actionWithDiffrentOutcomes();
}

void somefunction()
{
    //some code
}

и в класс:

class SomeClass()
{
    public:
        void addThingy(void (*function)());
        void actionWithDiffrentOutcomes();
    private:
        std::vector<void (**)()> vectoroffunctions;
}
SomeClass::addThingy(void (*function)())
{
    vectoroffunctions.push_back(&function);
}
SomeClass::actionWithDiffrentOutcomes()
{
    (*vectoroffunctions[0])();;
}

Я вроде как новичок в указателях, но я прочитал свои книги на c++, googled, ext. и это кажется правильным, компилируется, запускается, но когда я вызываю " actionWithDiffrentOutcomes ()", я получаю нарушение доступа. Я не знаю, что делать. это кажется правильным, но что-то явно не так. Так как я могу вызвать функцию из класса, когда определение находится в другом?

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

3 ответов


ваш код почти правильный. Ваш вектор ошибочно содержит указатели на указатели на функции, а не просто указатели на функции. addThingy добавить адрес function указатель на vector, но этот указатель выходит из области видимости в следующей строке.

измените код следующим образом:

//Store pointers to functions, rather than
//pointers to pointers to functions
std::vector<void (*)()> vectoroffunctions;

SomeClass::addThingy(void (*function)())
{
    //Don't take the address of the address:
    vectoroffunctions.push_back(function);
}

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


проблема:

vectoroffunctions.push_back(&function);

вы добавляете адрес местные переменной. Локальная переменная уничтожается, как только вы возвращаетесь из функции. Адрес, который вектор хранит указывает на уничтоженный объект, поэтому вы получаете "нарушение прав доступа" ошибка во время выполнения.

чтобы исправить это, сделайте следующее:

сначала измените это

std::vector<void (**)()> vectoroffunctions;

для этого:

std::vector<void (*)()> _functions; //vector of function-pointer-type
                                    //I changed the name also!

практически так же, как:

std::vector<void()> _functions; //vector of function-type

вот этого:

_functions.push_back(function); //add copy! 

чтобы сделать его более гибким, вы можете использовать шаблон вместе с std::function as:

class A
{
    public:
        template<typename Function>
        void add(Function && fn) 
        {  
            _functions.push_back(std::forward<Function>(fn)); 
        }
        void invoke_all()
        {
           for(auto && fn : _functions)
                fn();
        }
    private:
        std::vector<std::function<void()>> _functions;
};

теперь вы можете использовать его для хранения функций, а также функторов:

void myfunction() { std::cout << "myfunction" << std::endl ; }

struct myfunctor
{
       void operator()() { std::cout << "myfunctor" << std::endl ; }
};

A a;
a.add(myfunction);   //add function
a.add(myfunctor());  //add functor!
a.invoke_all();

выход (Онлайн Демо):

myfunction
myfunctor

надеюсь, что это поможет.


указатели функции гораздо более разборчивы с typedefs:

typedef void (*RequiredFunction)();

тогда вы можете объявить addThingy() такой:

    void addThingy(RequiredFunction function);

и vectoroffunctions вот так:

    std::vector<RequiredFunction> vectoroffunctions;

определение addThingy будет:

void SomeClass::addThingy(RequiredFunction function)
{
    vectoroffunctions.push_back(function);
}

и свой main() было бы больше похоже:

int main()
{
    SomeClass sc;
    RequiredFunction pointerfunc = somefunction;
    sc.addThingy(pointerfunc);
    sc.actionWithDiffrentOutcomes();
}

меньше *s и &s, с которым делать ошибки!