C++ Void* Questions
#1 Members - Reputation: 436
Posted 07 March 2012 - 09:57 PM
also, how would i store the address of the variables as a pointer?
int *p=0;//obviously
then store the address of p, so
a= point to p;
a=1;
//p is now 1
#2 Members - Reputation: 121
Posted 07 March 2012 - 10:51 PM
You can typecast it in whatever you like. (also all other types)
Example:
int* pixelArray = (int*)voidPtr;
Usually its a bad practice.. you must always think what your data is and what you do with it. But in some cases it can be unavoidable.
Pointer is an address.
So if you have a pointer of A, it means that the pointer contains the memory address where A is stored.
#3 Members - Reputation: 436
Posted 07 March 2012 - 11:02 PM
so this works?
bool a=true;
void foo(void* val)
{
//found its a bool
bool* nVal=(bool*)val;
if(nval==true){nval=false;}
}
foo((void*)&a);
#4 Moderator* - Reputation: 5410
Posted 07 March 2012 - 11:11 PM
#6 Members - Reputation: 436
Posted 07 March 2012 - 11:16 PM
#9 Senior Moderators - Reputation: 3113
Posted 08 March 2012 - 12:42 AM
In time the project grows, the ignorance of its devs it shows, with many a convoluted function, it plunges into deep compunction, the price of failure is high, Washu's mirth is nigh.
ScapeCode - Blog | SlimDX
#10 Members - Reputation: 3715
Posted 08 March 2012 - 01:36 AM
Its cleaner to use inheritance in this case.
Button that is derived specific per type.
I'd probably use templates or a union if i need a class dealing with multiple parameter types. in C++ a discriminated union such as boost::variant is prefered over a normal C style union due to the added type safety, C unions however work well enough if you do something similar to the SDL_Event union, (a union of a 1 byte type identifier and a set of structs where the structs all start with a 1 byte type identifier aswell).
For a GUI a signals/slots, event or callback mechanism would be preferable to having buttons with pointers to data owned by other parts of the program.
The voices in my head may not be real, but they have some good ideas!
#11 Members - Reputation: 380
Posted 08 March 2012 - 01:51 AM
if(nval==true){nval=false;}
I think this is not what you intended to do. You compare the pointer nval with true not the value nval points to.
Comparing any pointer with a boolean in C++ is legal. Its an artifact from C where
if (ptr) do something
compares the pointer against NULL. This is how pointer checking is done in a short form in C.
For C++ the pointer is converted to a boolean and afterwards compared.
You will not get a warning about that.
It shows a bit why type safe programming is a good thing and why void pointers should be avoided.
#12 Members - Reputation: 1178
Posted 08 March 2012 - 04:47 AM
i see. why is it bad practice? im on the verge of using it where i need different types for the same variable, which is alot.
so this works?
bool a=true;
void foo(void* val)
{
//found its a bool
bool* nVal=(bool*)val;
if(nval==true){nval=false;}
}
foo((void*)&a);
It's bad practice, because you're working around the type system of C and C++, so the compiler won't be able to check anything for you.
As others have pointed out, "union" can be used to treat one memory location as more than one type, but in this case, I'm sure there are even better ways using OO or templates.
One more thing: If you're using C++, also use C++ casts. In this case this one would be the correct one: bool* nVal=reinterpret_cast<bool*>(val);
This would make it clear to everyone what you're doing.
#13 Members - Reputation: 2042
Posted 08 March 2012 - 01:28 PM
You could use static_cast, in fact. The C++0x draft standard even defines reinterpret_casts between pointer types as if static_cast-ing through a void* intermediary (5.2.10.7).One more thing: If you're using C++, also use C++ casts. In this case this one would be the correct one: bool* nVal=reinterpret_cast<bool*>(val);
#14 Members - Reputation: 287
Posted 08 March 2012 - 09:27 PM
template <typename T> class MenuButton
{
public:
MenuButton( T* a_dataMember );
protected:
T* _dataMbr;
};This allows you to have a separate class for each type, without actually writing all the code to do that. Use it like:
float val1 = 3.14f;
MenuButton<float> fButton = MenuButton<float>(&val1);
char* val2 = "SomeString";
MenuButton<char> strButton = MenuButton<str>(&val2);
And if you need to access these different types using one type, so if you're putting these types in a list, use inheritance like so:
class MenuItemBase
{
// Stuff, abstract functions so you can actually use the child classes
};
template <typename T> class MenuButton : public MenuItemBase
{
// etc as above, except with some implementations of the abstract functions to allow you to use the class effectively
};But keep in mind, that any functions you declare for a templated class, must be defined before they are used. So you will have to do this:
// In the header file:
class MenuItemBase
{
public:
virtual void MyFunc(int&) = 0;
};
template <typename T> class MenuButton : public MenuItemBase
{
public:
virtual void MyFunc( int& x ) { x = 5; }
};
// Or this, also in the header file
class MenuItemBase
{
public:
virtual void MyFunc(int&) = 0;
};
template <typename T> class MenuButton : public MenuItemBase
{
public:
virtual void MyFunc( int& x );
};
template <typename T> void MenuButton<T>::MyFunc(int& x)
{
x = 5;
}
// Instead of more normal header class declaration then cpp class definitionI'm sorry that that's the way you'll have to define a template class, but take it up with those pricks on the c++ standards board who decided to make the export keyword a blank reserved keyword than to have to do any work whatsoever on their compilers to keep themselves compliant.
#15 Members - Reputation: 1969
Posted 09 March 2012 - 03:14 AM
A button in its basic form sends a single event in reaction to the user doing a single thing. It doesn't know and should not know what value might be changed somewhere else. A more advanced button will maybe send additional events for mouse over and whatnot... but it still does not know about anything outside its little box.
Some other piece of the application receives the generated event (via a callback or a message queue, or a socket, or whatever mechanism you like... a pigeon if you want), and that piece of code reacts to the event. It knows what value is to be changed in response (if there is one), and it knows its type.
#16 Members - Reputation: 432
Posted 09 March 2012 - 05:02 AM
I'm sorry that that's the way you'll have to define a template class, but take it up with those pricks on the c++ standards board who decided to make the export keyword a blank reserved keyword than to have to do any work whatsoever on their compilers to keep themselves compliant.
Well, if you want to keep the implementation separate from the interface you could still do it like this:
// in MenuButton.h
#ifndef MenuButton_h
#define MenuButton_h
class MenuItemBase
{
public:
virtual void MyFunc(int&) = 0;
};
template <typename T> class MenuButton : public MenuItemBase
{
public:
virtual void MyFunc( int& x );
};
#include "MenuButton.hpp"
#endif
// in MenuButton.hpp
template <typename T> void MenuButton<T>::MyFunc(int& x)
{
x = 5;
}
#17 Members - Reputation: 436
Posted 10 March 2012 - 12:14 AM
#18 Members - Reputation: 1565
Posted 10 March 2012 - 12:35 PM
Anyway, I have another suggestion to add to the (very good) advice above. I think I'd go with each button holding an std::function<void(void)>, and use lambda capture to automagically get references to the needed variables. This is because I suspect that you don't actually want to say to a button "here, set this variable when you're clicked" - it would be far more useful to you to be able to say to a button "here's an arbitrary bit of code - run it when you get clicked".
#include <functional>
#include <assert.h>
struct MyButton
{
void SetOnClickHandler(std::function<void(void)> handler)
{
onClickHandler = handler;
}
void OnClick()
{
if( onClickHandler )
{
onClickHandler();
}
}
std::function<void (void)> onClickHandler;
};
struct SomeGameLogicClassOrOther
{
void setupButton(MyButton& button)
{
auto myFunc = [&]()
{
//note m_buttonHasBeenClicked has been captured by reference
//=> you could capture other stuff by reference here too
//or just call a method on the SomeGameLogicClassOrOther
//which would allow you to do some checks or more complex logic
// - as Samoth pointed out would be useful
m_buttonHasBeenClicked = true;
};
button.SetOnClickHandler( myFunc );
}
bool m_buttonHasBeenClicked;
};
int main(int argc, char* argv[])
{
SomeGameLogicClassOrOther logic;
MyButton button;
logic.setupButton(button);
button.OnClick();
assert(logic.m_buttonHasBeenClicked);
return 0;
}std::function and lambda are really nice tools for doing this sort of thing in a generic yet type-safe way.
Edit: unless you don't need to change the behaviour of a button instance at run time, in which case I'd go for the template option.
#19 Members - Reputation: 1309
Posted 11 March 2012 - 03:15 AM
Well, im pretty good with not leaving behind errors, and i have gotten it to work perfectly. i like all the ideas, but a void* pointer would be the easiest solution. although some may say its bad practice, it only is if you dont use it right. thanks for the ideas.
sadly you just missed a chance to learn something that will make you a better programmer in the long run and the entire point of C++.
If this is a paid gig then fine, you got it working and you'll get paid. If this is something you do to learn, you did just learn the wrong thing.
Stoustrup.. the author of C++ calls "dangerous" programmers with obsolete programming practices "void* guys" .. you do the math ;)
#20 Members - Reputation: 287
Posted 11 March 2012 - 10:14 AM
Funnily enough void* and other dangerous sorts of programming are pretty much what leads to the types of errors I've found in the past that I had to do dangerous programming to debug...






