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, с которым делать ошибки!