С++, вызывающий функцию из вектора указателей функций внутри класса, где определение функции в основном
Хорошо, в моем основном я:
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])();;
}
Я вроде как новичок в указателях, но я читаю свои книги на С++, googled, ext. и это кажется правильным, компилируется, запускается, но когда я называю "actionWithDiffrentOutcomes()", я получаю нарушение доступа. Я не уверен, что делать. это кажется правильным, но что-то явно неправильно. Итак, как я могу вызвать функцию из класса, когда определение находится в другом?
Я делаю это так, потому что я не могу жестко закодировать каждый параметр в инструкции switch.
Ответы
Ответ 1
Ваш код почти правильный. Ваш вектор ошибочно держит указатели на указатели на функции, а не просто на указатели на функции. 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);
}
Кроме того, у вас много синтаксических ошибок в остальной части кода, которые должны помешать даже компиляции кода.
Ответ 2
Проблема здесь:
vectoroffunctions.push_back(&function);
Вы добавляете адрес переменной local. Локальная переменная будет уничтожена после возврата из функции. Адрес, который вектор сохраняет, указывает на уничтоженный объект, поэтому вы получаете ошибку "нарушение прав доступа" во время выполнения.
Чтобы исправить это, сделайте следующее:
Сначала измените это
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
как:
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
Надеюсь, что это поможет.
Ответ 3
Указатели функций гораздо более разборчивы с помощью 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();
}
Намного меньше *
и &
, чтобы совершать ошибки!