c ++ Class Method Pointer as Function Argument - c++

I am trying to create a dynamic function pointer that points to some methods all the methods I want to save on the array return a bool and have an uint32_t parameter. The functions are Service functions. These are intended to be dynamic, so when a class is started, the constructor links the service function from the object to be called from outside the object.
With the code below I am getting the following error:
Build error: ISO C++ forbids taking the address of an unqualified or parenthesized non-static member function to form a pointer to member function.
I have no clue what to do to overcome this problem, any idea would be greatly appreciated, thanks!
//File 1
typedef bool (*ServiceFunctionsType)(uint32_t);
//File 2
#include "File1.hpp"
extern uint8_t ServiceFunctions_size;
extern ServiceFunctionsType *ServiceFunctions;
void Service_Functions_Setup();
bool SetPtr(ServiceFunctionsType a);
void ClearPtr(uint8_t id);
//File 3
#include "File1.hpp"
ServiceFunctionsType *ServiceFunctions;
uint8_t ServiceFunctions_size = 0;
//File 4
#include "File2.hpp"
#include <stdlib.h>
void Service_Functions_Setup()
{
ServiceFunctions = NULL;
if(SERVICE_FUNCTION_POINTER_START_SIZE != 0)
{
ServiceFunctions_size = SERVICE_FUNCTION_POINTER_START_SIZE;
ServiceFunctions = (ServiceFunctionsType*)malloc(sizeof(ServiceFunctionsType)*SERVICE_FUNCTION_POINTER_START_SIZE);
for(uint8_t i = 0; i < SERVICE_FUNCTION_POINTER_START_SIZE; i++)
{
ServiceFunctions[i] = NULL;
}
}
}
uint8_t SetServiceFunctionPointer(ServiceFunctionsType a, bool _realloc)
{
if( ServiceFunctions == NULL )
{
ServiceFunctions = (ServiceFunctionsType*)malloc(sizeof(ServiceFunctionsType));
ServiceFunctions[0] = a;
return 0;
}
for(uint8_t i = 0; i < ServiceFunctions_size; i++)
{
if( ServiceFunctions[i] == NULL )
{
ServiceFunctions[i] = a;
return i;
}
}
if(_realloc)
{
ServiceFunctions_size++;
ServiceFunctions = (ServiceFunctionsType*)realloc(ServiceFunctions,sizeof(ServiceFunctionsType)*ServiceFunctions_size);
ServiceFunctions[ServiceFunctions_size - 1] = a;
return ServiceFunctions_size - 1;
}
return INVALID_SERVICE_FUNCTION_POINTER;
}
void ClearServiceFunctionPointer(uint8_t id)
{
ServiceFunctions[id] = NULL;
}
//File 5
class MonoStepSequencer
{
public:
MonoStepSequencer();
~MonoStepSequencer();
uint8_t ServicePointerID;
bool Service(uint32_t time);
private:
};
//File 6
#include "File2.hpp"
MonoStepSequencer::MonoStepSequencer()
{
ServicePointerID = SetServiceFunctionPointer(&this -> Service);
}
//This is the function to be called with a pointer
bool MonoStepSequencer::Service(uint32_t time)
{
//Some Code
}

You can try, to use lambdas. Create method like
std::function<void()> getService()
Where inside you can use:
return [this](){
Service();
};
Also if your methods should use arguments, you can use this method, but add arguments into return value and lambda.
One more, you can create lambda outside of class methods, like:
[&object]()
{
object.Service();
}
In this way, better to use std::shared_ptr to guŠ°rantee that object exists, when lambda called.

this -> Service is an unqualified or parenthesized non-static member function
You probably meant :: instead of -> Also, you need a type on the left, not a variable.
Also, please don't put spaces around ->. That makes it look like you're specifying a trailing return type or something.

Related

Can not call function pointer of a struct to a class method

use C++98. I have a struct t_fd which is used inside a class MS. In the struct there are two pointers to function: fct_read, fct_write. I designed that the function pointers are pointing to the two methods of the class. But then I have this error when trying to call them.
expression preceding parentheses of apparent call must have (pointer-to-) function type.
Please advice on the error, also on the design. I need the two functions are methods of that class because I need to use class's attributes (even though it isn't showed here for the shake of simplicity). Thank you for your time, I appreciate your help!
#include <vector>
#include <iostream>
typedef struct s_fd {
void(MS::*fct_read) (int);
void(MS::*fct_write) (int);
} t_fd;
class MS
{
private:
std::vector< t_fd > _fdSet;
void server_accept(int s)
{
if (s % 2 == 0)
_fdSet[cs].fct_read = MS::client_read;
else
_fdSet[cs].fct_write = MS::client_write;
}
void client_read(int fd)
{
std::cout << "I'm reading\n";
}
void client_write(int fd)
{
std::cout << "I'm writing\n";
}
void check_fd()
{
int i = 0;
int size = 10;
while (i < size)
{
if (i < 5)
_fdSet[i].fct_read(i); //Error here!
if (i >= 5)
_fdSet[i].fct_write(i); //Error here!
i++;
}
}
};
The intent of your code is difficult to understand (in its current form). But I would be happy to solve few issues in your code.
MS class needs to be declared before you reference it the type from s_fd structure definition :
class MS; // forward declaration
typedef struct s_fd {
void(MS::* fct_read) (int);
void(MS::* fct_write) (int);
} t_fd;
class MS
{ ... }
the syntax to assign function pointer is incorrect. You forgot &:
_fdSet[cs].fct_read = &MS::client_read;
fct_read and fct_write are member function pointers. They should be applied on instance of MS class. In case you want to apply them on this object:
if (i < 5) {
auto fptr = _fdSet[i].fct_read;
(this->*fptr)(i);
}

Accessing multilayered structs results in error

I'm working on a homework assignment that involves creating structures for vending machines around campus. I'm getting the error "'vendingMachines' was not declared in this scope" and I can't figure out the solution. Would I have to run a for loop in main to declare the vendingmachines struct?
struct Location
{
std::string buildingName;
int floorLevel;
};
struct Drink
{
std::string drinkName;
float drinkSize;
float drinkPrice;
};
struct VendingMachine
{
Location machineLocation;
Drink drinkTypes[10];
};
struct AllVendingMachines
{
VendingMachine vendingMachines[5];
};
int checkPurchase(std::string buildingName, int floorLevel, std::string drinkName, f$
{
bool correct = true;
for (int i = 0; i < 5; i++)
{
if (vendingMachines[i].machineLocation.buildingName != buildingName)
{
correct = false;
}
if (vendingMachines[i].machineLocation.floorLevel != floorLevel)
{
correct = false;
}
for (int c = 0; c < 10; c++)
{
if (vendingMachines[i].drinkTypes[c].drinkName != drinkName)
{
correct = false;
}
if (vendingMachines[i].drinkTypes[c].drinkSize != drinkSize)
{
correct = false;
}
}
}
if (correct == true)
{
return 1;
}
else
{
return 0;
}
}
You're attempting to access vendingMachines in checkPurchase().
However, that's a member of the struct AllVendingMachines. Which means each AllVendingMachines object will have a vendingMachines array. So whose vendingMachines are you trying to access?
The simplest solution I can see would be to take an AllVendingMachines object as a function argument:
int checkPurchase(std::string buildingName, int floorLevel, std::string drinkName, AllVendingMachines machines)
{
bool correct = true;
for (int i = 0; i < 5; i++)
{
if (machines.vendingMachines[i].machineLocation.buildingName != buildingName)
{
correct = false;
}
// ...
You have declared vendingMachines to be part of struct AllVendingMachines, but you have never created an instance of that struct. Therefore, not a single instance of the member array 'vendingMachines' exists.
You could simply make the array vendingMachines a global variable, i.e. move it out of struct AllVendingMachines, or you could create a global instance of struct AllVendingMachines, by changing the declaration to the following:
struct AllVendingMachines
{
VendingMachine vendingMachines[5];
} all_vending_machines_global_instance;
In the latter case, you must change all references to vendingMachines[i] in the function checkPurchase to all_vending_machines_global_instance.vendingMachines[i].
I don't want to encourage the use of long variable names, I just gave it this long name for clarity.
Alternatively, if you don't want to use global variables, you can make the function checkPurchase receive an additional paramater consisting of a pointer or reference to an instance of struct AllVendingMachines or directly to an instance of the vendingMachines member array.

std::find return a class that I can't acesses functions

I come from C/C# language and now I'm trying to learn about C++ and his standards functions.
Now, I'm creating a class called IMonsterDead. I will have a std::vector<IMonsterDead*> with N monsters.
Example:
class IMonsterDead {
public:
IMonsterDead(int Id)
{
this->_Id = Id;
}
virtual void OnDead() = 0;
int Id() const {
return _Id;
}
private:
int _Id;
};
One class which implements that class:
class MonsterTest : public IMonsterDead {
public:
MonsterTest(int generId)
: IMonsterDead(generId)
{
}
virtual void OnDead()
{
std::cout << "MonsterTesd died" << std::endl;
}
};
Ok, if I access directly everything works fine. But I'm trying to use std::find.
Full program test:
int main()
{
std::vector<IMonsterDead*> monsters;
for (int i = 0; i < 1000; i++)
{
monsters.emplace_back(new MonsterTest(1000 + i));
}
int id = 1033;
std::vector<IMonsterDead*>::iterator result = std::find(monsters.begin(), monsters.end(), [id]( IMonsterDead const* l) {
return l->Id() == id;
});
if (result == monsters.end())
std::cout << "Not found" << std::endl;
else
{
// Here I want to access OnDead function from result
}
return 0;
}
So I need to access OnDead function from result but I can't. Intellisense doesn't show anything for me. The result exists.
How can I access that function? Have another better way to do that?
You need to use std::find_if() instead of std::find(). std::find() is for finding an element with a specific value, so you have to pass it the actual value to find, not a user_defined predicate. std::find_if() is for finding an element based on a predicate.
Either way, if a match is found, dereferencing the returned iterator will give you a IMonsterDead* pointer (more accurately, it will give you a IMonsterDead*& reference-to-pointer). You need to then dereference that pointer in order to access any members, like OnDead().
You are also leaking memory. You are not delete'ing the objects you new. And when dealing with polymorphic types that get deleted via a pointer to a base class, the base class needs a virtual destructor to ensure all derived destructors get called properly.
With that said, you are clearly using C++11 or later (by the fact that you are using vector::emplace_back()), so you should use C++11 features to help you manage your code better:
You should use std::unique_ptr to wrap your monster objects so you don't need to delete them manually.
You should always use the override keyword when overriding a virtual method, to ensure you override it properly. The compiler can catch more syntax errors when using override than without it.
You should use auto whenever you declare a variable that the compiler can deduce its type for you. Especially useful when dealing with templated code.
Try something more like this:
#include <iostream>
#include <vector>
#include <memory>
#include <algorithm>
class IMonsterDead {
public:
IMonsterDead(int Id)
: m_Id(Id)
{
}
virtual ~IMonsterDead() {}
virtual void OnDead() = 0;
int Id() const {
return m_Id;
}
private:
int m_Id;
};
class MonsterTest : public IMonsterDead {
public:
MonsterTest(int generId)
: IMonsterDead(generId)
{
}
void OnDead() override
{
std::cout << "MonsterTest died" << std::endl;
}
};
int main()
{
std::vector<std::unique_ptr<IMonsterDead>> monsters;
for (int i = 0; i < 1000; i++)
{
// using emplace_back() with a raw pointer risks leaking memory
// if the emplacement fails, so push a fully-constructed
// std::unique_ptr instead, to maintain ownership at all times...
monsters.push_back(std::unique_ptr<IMonsterDead>(new MonsterTest(1000 + i)));
// or:
// std::unique_ptr<IMonsterDead> monster(new MonsterTest(1000 + i));
// monsters.push_back(std::move(monster));
// or, if you are using C++14 or later:
// monsters.push_back(std::make_unique<MonsterTest>(1000 + i));
}
int id = 1033;
auto result = std::find_if(monsters.begin(), monsters.end(),
[id](decltype(monsters)::value_type &l) // or: (decltype(*monsters.begin()) l)
{
return (l->Id() == id);
}
// or, if you are using C++14 or later:
// [id](auto &l) { return (l->Id() == id); }
);
if (result == monsters.end())
std::cout << "Not found" << std::endl;
else
{
auto &monster = *result; // monster is 'std::unique_ptr<IMonsterDead>&'
monster->OnDead();
}
return 0;
}
Iterators are an interesting abstraction, in this case to be reduced to pointers.
Either you receive the pointer to the element or you get an invalid end.
You can use it as a pointer: (*result)->func();
You can also use it to create a new variable:
IMonsterDead &m = **result;
m.func();
This should give the same assembly, both possible.

Having the same member function have different definitions for different class instances

Is it possible for the same member function to have different definitions for different objects of that class?
IMPORTANT NOTE: I cannot use a callback like in this solution. (reason explained below example)
Lets say we have this object:
struct object
{
int n;
int m;
void f();
};
Is it possible to have something like:
object a,b;
// and here to define the functions
a.f() {std::cout << n+m;}
b.f() {std::cout << n-m;}
The reason i cannot use a callback is because the function i want to define will be recursive and will overflow. What i am trying to do with this method is to create an immitation of the stack (but all the variables are stored on heap as a double chained list) and so i will call a void (void) function that has no local variables thus increasing the stack depth the function can achieve. Also important to mention is that i want to make a header file with this idea. For further context explination, this is how it should work:
MyHeader.h
template <typename PARAM_TYPE> class HEAP_FUNCTION
{
private:
struct THIS_CALL // ! THIS HAS NOTHING TO DO WITH THE __thiscall CALLING CONVENTION !
{
PARAM_TYPE* PARAM;
THIS_CALL* next_call;
THIS_CALL* prev_call;
};
THIS_CALL* FIRST_CALL;
THIS_CALL* CURRENT_CALL;
public:
HEAP_FUNCTION(PARAM_TYPE* FirstCall)
{
FIRST_CALL = new THIS_CALL;
CURRENT_CALL = FIRST_CALL;
FIRST_CALL->PARAM = *FirstCall;
}
HEAP_FUNCTION(PARAM_TYPE FirstCall)
{
FIRST_CALL = new THIS_CALL;
CURRENT_CALL = FIRST_CALL;
FIRST_CALL->PARAM = FirstCall;
}
~HEAP_FUNCTION()
{
delete FIRST_CALL;
}
void call(void);
};
Source.cpp
// This is the ilustration of the recursive method for calculating
// the 1+2+3+...+n sum.
// The "normal" definition for this function would be:
//
// unsigned long long sum(unsigned long long n)
// {
// if (n == 0) return 0;
// return n + sum(n-1);
// }
//
// The function presented bellow is the equivalent.
struct Param
{
unsigned long long n;
unsigned long long return_value;
}
int main()
{
Param start_value;
start_value.n = 10; // we will calculate 1+2+...+10
HEAP_FUNCTION<Param> Gauss(&start_value);
// We imagine this is where i define call().
// The code written in this definiton works correctly.
Gauss.call()
{
// Test if the function needs to stop further calls.
if(CURRENT_CALL->PARAM->n == 0)
{
CURRENT_CALL->PARAM->return_value = 0;
return;
}
// Prepare the parameters for the next function call.
CURRENT_CALL->next_call = new THIS_CALL;
CURRENT_cALL->next_call->PARAM = new PARAM_TYPE;
CURRENT_CALL->next_call->prev_call = CURRENT_CALL;
CURRENT_CALL->next_call->PARAM->n = CURRENT_CALL->PARAM->n - 1;
// Call the next instance of the function.
CURRENT_CALL = CURRENT_CALL->next_call;
call();
CURRENT_CALL = CURRENT_CALL->prev_call;
// Collect the return value of the callee.
CURRENT_CALL->PARAM->return_value = CURRENT_CALL->PARAM->n + CURRENT_CALL->next_call->PARAM->return_value;
// Delete the space used by the callee.
delete CURRENT_CALL->next_call;
}
// This is the actual call of the function.
Gauss.call();
// The return value is found in the start_value struct.
std::cout << start_value.return_value << std::endl;
return 0;
}
IMPORTANT NOTE: Derivering the entire class will result in a single call() definition for funtions like sum(a, b) and dif(a, b) since they will use the same PARAM struct. (Even though they are not recursive, and the probability of someone using this is very small, this method is good in a bigger program when some of your functions will have a lot of parameters and just placing them on the heap will result in more stack space)
Don't think I understood the question properly, but did you consider function overloading?

VC++ "Re-use" a function?

How can I re-use a function?
Okay lets say I have this "main" function below:
bool A = false;
bool B = true;
void MainFunction(bool Whatever) {
if(!Whatever) {
A = true;
if(A) {
B = false;
} else if(!A) {
B = true;
}
}
}
Now I want to make a new function using the MainFunction, something like this:
MainFunction ANewFunction(false);
MainFunction AnotherNewFunction(true);
Obviously that won't work, so is there any way to "re-use" a function as a different function?
You're welcome to have one function call another. For example:
void ANewFunction() {
MainFunction(false);
}
void AnotherNewFunction() {
MainFunction(true);
}
You can even get fancy:
#include <functional>
auto ANewFunction = std::bind(&MainFunction, false);
auto AnotherNewFunction = std::bind(&MainFunction, true);
Either way, you can call ANewFunction or AnotherNewFunction, and MainFunction will get called with the given argument. (In the latter case, they're not really functions anymore. They're called function objects, or functors, but you cal still call them just like ordinary functions: ANewFunction().)
You can't "re-use" functions, at least not in the way I understand your question.
But you can create a new function that calls the original function and then does some additional work of its own. For example:
void PrevFunction(int one)
{
int i = one;
// do whatever
}
void NewFunction(int one)
{
PrevFunction(one);
// do new stuff
// ...
}
You could also define a class, and then use inheritance and virtual functions to modify the behavior of a particular set of functions from the base class.
typedef int (*function_t)(int); // new type - defines function type - address of function
// your function, PrevFunction is simply variable holding address of the function:
int PrevFunction(int one) { return one; }
// new variable of type function_t initialized by PrevFunction address:
function_t NewFunction = PrevFunction;
//And finally we can use either PrevFunction or NewFunction - they point to the same function body:
int a = PrevFunction(1); // a == 1
int b = NewFunction(2); // a == 2
Simply call MainFunction from your other function?
void ANewFunction()
{
MainFunction(false);
}
void AnotherNewFunction()
{
MainFunction(true);
}
If your question is how do you make AnotherNewFunction refer to a different A and B than ANewFunction, the answer is you can't, at least not without help from MainFunction. You can, however, update MainFunction:
void MainFunction(bool Whatever, bool& A, bool& B) {
if(!Whatever) {
A = true;
if(A) {
B = false;
} else if(!A) {
B = true;
}
}
}
bool A1 = false;
bool B1 = true;
void ANewFunction()
{
MainFunction(false, A1, B1);
}
bool A2 = false;
bool B2 = true;
void AnotherNewFunction()
{
MainFunction(true, A2, B2);
}
Another new-fangled solution, using lambda's:
auto ANewFunction = [](){ MainFunction(false); }
auto AnotherNewFunction = [](){ MainFunction(true); }