In my main function I create an array of objects of a certain class "Menu"
And when I call a function I want to provide a pointer to that array.
Menu menu[2];
// Create menu [0], [1]
Function(POINTER_TO_ARRAY);
Question: What is the correct way to write the Function parameters?
I try:
Function(&menu);
and in Header file:
void Function(Menu *menu[]); // not working
error: Cannot convert parameter 1 from Menu(*)[2] to Menu *[]
void Function(Menu * menu); // not working
error: Cannot convert parameter 1 from Menu(*)[2] to Menu *[]
and I can't come up with any other way to do this and I can't find a solution to this particular problem.
Simply, I want to be able to access the Menu array within the function through a pointer. What are the difference in normal pointer to a pointer to an array?
Declaration:
void Function(Menu* a_menus); // Arrays decay to pointers.
Invocation:
Function(menu);
However, you would need to inform Function() how many entries are in the array. As this is C++ suggest using std::array or std::vector which have knowledge of their size, beginning and end:
std::vector<Menu> menus;
menus.push_back(Menu("1"));
menus.push_back(Menu("2"));
Function(menus);
void Function(const std::vector<Menu>& a_menus)
{
std::for_each(a_menus.begin(),
a_menus.end(),
[](const Menu& a_menu)
{
// Use a_menu
});
}
Either by const or non-const pointer
void Function(Menu const* menu);
void Function(Menu* menu);
...or by const or non-const reference
void Function(Menu const (&menu)[2]);
void Function(Menu (&menu)[2]);
which can be generalized to a template so that the array size will be deduced by the compiler:
template<size_t N> void Function(Menu const (&menu)[N]);
template<size_t N> void Function(Menu (&menu)[N]);
Always call as Function(menu);
Should work if you use
void Function(Menu * menu);
and call using
Function(menu);
instead of
Function(&menu);
passing the array name causes it to decay to a pointer to the type contained in the array. However, as #hmjd says in his answer you will also need to pass the array size, so his suggestion of using a vector is favourable if this option is open to you.
You can use
Function((void *) whatever_pointer_type_or_array_of_classes);
in your main.
And in the function:
type Function(void * whatever)
{
your_type * x =(your_type *) whatever;
//use x
....
x->file_open=true;
....
}
Related
I have written a function that takes in a dynamic length array but with fixed inner array size, the second parameter in the function is the length of the parent array. When I try to access the nested values however, I get the issue mentioned above.
void myFunc(int arrOfArr, int arrOfArrLen) {
// try to access
arrOfArr[0][1]; // expect val2
}
example usage
myFunc(
{
{val1, val2},
{val3, val4}
},
2
);
edit: I realize "contextually" obviously an integer has no indexes, but that's how you declare an array it seems...(truthfully in Arduino context) but apparently it's still C++
Here's a runable demo of above from the first sandbox Google returned
http://cpp.sh/5sp3o
update
I did find a solution, it's ugly but it works:
instead of passing in a "raw" nested array as a param, I set it as a variable first eg:
int arrOfArr[][3] = {
{val1, val2},
{val3, val4}
}
Then in the function I do the same thing
void myFunc(int arrOfArr[][3], int arrOfLen) {
// access
}
Call it
myFunc(arrOfArr, 2);
As I said it's ugly but works for me, this is a passing project thing not a low-level dev, maybe will learn it fully later on but not needed in day job.
edit: apparently the thing I was trying to do initially eg. embed an initializer list as a param does not work.
if you want to pass a nested array, the declaration may be:
template<size_t N>
void myFunc(int const arrOfArr[][N], int arrOfArrLen) {
// ...
}
and you can remove the template argument if N is already decided.
const size_t N = 3;
void myFunc(int const arrOfArr[][N], int arrOfArrLen) {
// ...
}
but it doesn't work if you pass a brace-enclosed initializer, you can add a overloaded function:
template<size_t M, size_t N>
void myFunc(int const (&arrOfArr)[M][N], int arrOfArrLen){
// attention: int *const*
// ...
}
I'm sort of new to C++ and programming in general. I'm making a pokemon remake of the old gameboy version for fun, and I'm having trouble passing a whole structure as an arguement.
This is a shortened version to highlight the problem I'm having:
struct Enemy_Pokeman
{
string opp_name;
int num_pokeman;
int pokeman_LVL;
};
void pl_Pokeman(Enemy_Pokeman);
void pokeman_data(string opp_name, int num_pokeman, int pokeman_ID[], int pokeman_LVL[],
int purpose)
{
Enemy_Pokeman enemypokeman[num_pokeman];
enemypokeman[0].opp_name = opp_name;
enemypokeman[0].num_pokeman = num_pokeman;
for(int i=0; i<num_pokeman; i++)
enemypokeman[i].pokeman_LVL = pokeman_LVL[i];
pl_Pokeman(enemypokeman); //Function call - Codeblocks detects error
//on this line
}
void pl_Pokeman(Enemy_Pokeman enemy)
{
cout << endl;
}
Sorry if this doesn't make sense, I didn't want to post the entire thing, so I chopped it up a bit.
The problem is that it won't accept Enemy_Pokeman as an arguement.
Function pl_Pokeman only takes Enemy_Pokeman type while you passed in an array of Enemy_Pokeman
You update pl_Pokeman function to take array as input:
void pl_Pokeman(Enemy_Pokeman enemy[], int arraySize);
Or
template<typename T, size_t N>
void pl_Pokeman(Enemy_Pokeman (&enemy)[N])
you're passing to your function whole array of Enemy_Pokemans, not just one element. function expects one element only. also, you're creating that array within a function, so it's a local variable. if function pokemon_data returns, that array will be destroyed.
For Single structure-
When you are passing the structure as a argument, you should pass with & operator.
pl_Pokeman(&enemypokeman); // Fix 1
While catching it you need to catch it with Structure pointer.
void pl_Pokeman(Enemy_Pokeman *); // Fix 2
For Array of structure-
pl_Pokeman(&enemypokeman,size); // pass it with size
while catching it
void pl_Pokeman(Enemy_Pokeman (*)[], int );
I would like to forward a callback to a function pointer. So I declare a static (int*) m_pointer1, as well as a method void RegisterCallback1( (int*)fct)
in class1.h:
public:
int RegisterCallback1( int (*fct) );
private:
static int (*m_Callback1);
in class1.cpp:
int class1::RegisterCallback1( int (*fct) )
{
m_Callback1= fct;
}
then, I want to forward the callback to the function pointer:
void class1::Callback1()
{
(*m_Callback1)();
}
But I get a compiler error "Expression must have (pointer-to)- function type
I have followed tutorial and read about function pointers and they seem to do it this way without any problems. Any ideas why?
EDIT:
So, I declare (int*)(void)m_Callback1 -Visual Studio requires a void there...-
Then how do I call the registerCallback function with the argument?
class1.RegisterCallBack1( ??? - class2::callback -??? );
static int (*m_Callback1) does not declate a function pointer, just a pointer to int: you forgot about the parameter list. You meant:
static int (*m_Callback1)();
and
int RegisterCallback1( int (*fct)() );
You haven't declared a function pointer, you've declared a normal data pointer. You are missing () at the end of the declaration.
You can try to limit the missing () errors pointed out by Oli and Dave by using a typedef for the callback function's signature: typedef int (*)() CallBack; This would at least have the merit of letting you think once about the precise number of brackets rather than at every point in your code where you use such a function.
So I'm still rather new to programming/C++, and still trying to wrap my head around pointers and passing by reference and everything. A program I'm trying to figure out now needs to pass an array of structs to another function. I've gotten it working by just passing the array directly there. It seems to work fine. However, what I'm concerned about is that I believe I'm passing it by value, and I understand that it's better to pass structs by reference, so you're not making a copy of the struct every time...
Anyway, here's a basic example of what I'm doing:
struct GoldenHelmet {
int foo;
string bar;
};
void pass (GoldenHelmet ofMambrino[], int size);
int main () {
GoldenHelmet ofMambrino[10];
int size = sizeof(ofMambrino) / sizeof(ofMambrino[0]);
ofMambrino[1].foo = 1;
pass(ofMambrino, size);
cout << ofMambrino[2].foo << endl;
return 0;
}
void pass (GoldenHelmet ofMambrino[], int size) {
ofMambrino[2].foo = 100;
ofMambrino[2].bar = "Blargh";
}
From what I understand, it works because arrays are already pointers, right? But the way I have that configured, am I still passing a copy of the struct and everything to the pass() function? I've tried to pass it by reference, but it doesn't seem to want to work any way I've tried.
The C++ way:
#include <array>
typedef std::array<GoldenHelmet, 10> Helmets;
void pass(Helmets &);
int main()
{
Helmets h;
h[1].foo = 1;
pass(h);
//...
}
void pass(Helmets & h)
{
h[2].foo = 100;
// ...
}
Indeed, we pass the array by reference.
This syntax:
void pass (GoldenHelmet ofMambrino[], int size)
is actually quite confusing. Because you are not passing an array, you are passing a pointer. They are not the same thing though, don't get confused. This oddity only applies to function parameters. The above is exactly identical to this:
void pass (GoldenHelmet * ofMambrino, int size)
It's actually impossible to pass an array by value, unless it is a sub-object of another object. You can pass them by reference, you need to include the size though, but you can do that using a template:
template<int N>
void pass (GoldenHelmet (&ofMambrino)[N])
These are all possible, but none of them are pass by value. Just think of ofMambrino as being the address of the beginning of the array, and that is what you are passing.
void pass (GoldenHelmet ofMambrino[], int size)
void pass (GoldenHelmet ofMambrino[10], int size)
void pass (GoldenHelmet *ofMambrino, int size)
void pass (GoldenHelmet (&ofMambrino)[10], int size)
Arrays are represented and passed as pointers, so you are not copying anything here. In contrast, if you were passing a single struct, it would be passed by value.
Below is a code snippet to illustrate this last point:
void passByVal (GoldenHelmet ofMambrino) {
ofMambrino.foo = 100;
ofMambrino.bar = "Blargh";
}
void passByRef (GoldenHelmet& ofMambrino) {
ofMambrino.foo = 100;
ofMambrino.bar = "Blargh";
}
int main() {
GoldenHelmet h;
passByVal(h); // h does not change
passByRef(h); // fields of h get assigned in the call
}
First of all array is not pointers. We refer this as a pointer in the argument list because when we use
int x[ ]
x is actually const pointer that points the beginning of the array. And when you pass this to a function you send the adress of the memory that is beginning of the array. Thats why when you make a change in your function, you make change in the adress of your variable in the caller section actually. This is actualy simulated call by reference not call by reference. But effect is same with call by reference because you are working on memory locations. For this reason when you send array of your struct you pass actually adress of your array of structs. Thats why when you change value on this, you actually change your structs.
To use call by reference, one thing you must to do is to define your function prototype like
void f(int ¶m)
and when calling function, it is same with the others.
To summarize:
int main()
{
int x;
// simulated call by reference that use adress of variable,
// lets say adress of x is 19ff
f(&x); // actually you send 19ff
f(x); // call by reference that use reference of variable
}
// simulated call by reference
void f(const int *y)
{
// when you use like *y=10, you are writing on memory area 19ff, you actually
// change memory area that is belong to x in the main
}
// call by reference
void f(const int &y)
{
}
how do I cast void *something to an object in standard C++?
Specifically I want want to cast void *userdata
to std::map<String, void*>
Is this possible? I am trying:
//void *user_data is a parameter of this function (callback)
std::map <String, void*> user_data_n; //this line is ok
user_data_n = static_cast<std::map<String, void *>>(*user_data); //I get the errors here.
ERRORs:
Spurious '>>' user '>' to terminate a template argument list
Expected '>' before '(' token
'void *' is not a pointer-to-object type
or is there a better way to carry information about the caller object and some other parameters I can pass to void *user_data?
UPDATE:
Ass suggested by #aaa carp I changed >> to > > and the first two errors were solved. The last is strange, Why do I get that kind of message when casting it here and not when putting that object when setting the callback?
std::map<String, void*> user_data_h;
user_data_h["Object"] = this; //this is a MainController object
user_data_h["h"] = h; //h was defined as int *h
createTrackbar("trackbar_H", winName, h, 255, trackbar_handler, &user_data_h);
where createTrackbar is defined as:
int createTrackbar( const string& trackbarname, const string& winname,
int* value, int count, TrackbarCallback onChange, void* userdata);
UPDATE2:
doing this solved my problem but following the same approach, why I still get error when trying to cast objects contained in my map object?
void trackbar_handler(int value, void *user_data){
std::map <String, void*> *user_data_map;
user_data_map = reinterpret_cast<std::map<String, void *> *>(user_data); //WORKED!! ;)
MainController *controller; //the same class type I put using "this" above
controller = reinterpret_cast<MainController *>( user_data_map["Object"]); //ERROR here
int *var = reinterpret_cast<int*> (user_data_map["h"]); //ERROR also here
>> should be > >
and you do not want to dereference void pointer, instead cast void pointer to desired pointer type and then dereference
#casa has already provided you with answer to second problem
When you're casting from a void *, your result will be a pointer too. So the map declaration should be:
std::map <String, void*> *user_data_n;
Second, you should use reinterpret_cast for such (potentially dangerous) casts:
user_data_n = reinterpret_cast<std::map<String, void *> *>(user_data);
Update:
As others suggested, you could simply use a static_cast as well.
Why do I get that kind of message when casting it here and not when putting that object when setting the callback?
Any pointer can be implicitly converted to void *, but when converting it back to a pointer of some specific type, you need an explicit cast.
why I still get error when trying to cast objects contained in my map object?
As already mentioned in the comments, you need to dereference the pointer before using the map object. You might want to define a reference instead to make things easier:
std::map <String, void*> &user_data_map =
*(static_cast<std::map<String, void *> *>(user_data));
An noted, the >> in that line to close your template should be > > (with a space).
Also, if user_data is a void pointer, you cannot dereference it. You could cast the pointer to another pointer type with reinterpret_cast:
std::map <String, void*> *user_data_n_ptr; //note this is a pointer to a map.
user_data_n_ptr = reinterpret_cast<std::map<String, void *> *>(user_data);
This will cast the void pointer to a std::map .
You should be careful with this. void pointers shouldn't typically be thrown around in c++. There may be a better way to do what you want and avoid void * all together.
I suppose this is for serving a C callback? It might be better to have a specialized struct which keeps all those values using the exact types. That way you'd be down to one cast for the whole thing. Something like this:
struct callback_user_data {
my_class* that;
int number;
callback_user_data(my_class* p, int i) : that(p), number(i) {}
};
// the callback
void my_callback(void* user_data)
{
callback_user_data* cbud = static_cast<callback_user_data*>(user_data);
somehow_use(cbud->that, cbud->number);
}
//call the function, passing our user data
callback_user_data cbud(this, 42);
some_function_taking_our_callback(&my_callback, &cbud);
Note that usually I have this seen (and used) this so that not a special type is passed, but only this, which has all the necessary data anyway:
// the callback
void my_callback(void* user_data)
{
my_class* that = static_cast<my_class*>(user_data);
that->f();
std::cout << that->number << '\n';
}
//call the function, passing our user data
some_function_taking_our_callback(&my_callback, this);