![]() |
Void Pointers Question about dereferencing
I have been experimenting with void pointers. I have encountered many problems, since I want to implement them into a very big project, but I made some examples that I believe that if I understand them, I will be able to use them efficiently.
Here is my first example: :
The result I am getting is '0xbffff9c0' from the cout function. Actually, I had predicted it, but I don't know how can I access the contents of the void pointer. Can you help? Another example: :
:
Can you please explain to me why this is happenning (in both examples) and what can I do to dereference a void pointer so that I can access the elements it points to? |
the whole 'point' of a void pointer is to point to an object of unknown type at run-time, rather than compile-time. this is usually done with polymorphism (one thingie can be one of many thingies). the simple example can be animal sounds.
you start your program with several classes, all inheriting from the abstract class animal. it has a pure virtual function known as sound, (denoted by function_name() = 0) which has the property of echoing the animal sounds by those which the user has decided upon. we use a switch @ run-time to find out which animal sound we should make! if this doesn't make sense, read up on c++ and polymorphism. good luck! |
Bl00d, this has nothing to do with polymorphism.
Quote:
Now, to answer your question..... C++ output streams (of which cout is one) provide an operator<< which takes a void pointer, and prints the address contained in the pointer to the stream. It is not possible to "access" the contents of a void pointer directly as, by definition, a void pointer points at nothing in particular (i.e. there are no contents to access). The point (no pun intended) of void pointers is that they can point at anything. If you want to access whatever is being really pointed at, you (the programmer) need to know the type of what is really being pointed at. If you know that the pointer actually points at an int, convert the void pointer into a pointer to int. To get the value of that int, dereference the pointer to int. In code, in your example, you would do this as; :
std::cout << *(static_cast<int *>(v));One problem with void pointers is that they can be converted to anything. So you could also do this; :
std::cout << *(static_cast<float *>(v));Comment to ponder on as you get more advanced: in practice, printing an int as a float will often yield garbage output. Technically, it is actually undefined behaviour (as that term is defined in the C++ standard), and a program crash is an equally correct outcome. Quote:
The reason is that the "%s" format specifier you have supplied explicitly tells the printf() function that p is actually a C-style string. Quote:
If you want the stream to print out the string "Hello", you need to convert the void pointer into a pointer to char. When it receives a pointer to char, the stream operators (by convention) treat it as a C-style string (an array of char, with the last one being a char with value zero. :
void f(void *p){ |
yeah, about that...this is one of those posts where you need to calll the number below...i am currently wasted.
|
I see. Thanks a lot for clearing all these stuff up for me, grumpy. Also, I knew about cout not being a function, but I had to go afk immediately, and it seems I didn't quite realize what I was typing there. Whatever the case, thanks a lot.
As far as void pointers are concerned, here is the thing I want to do: I want to create a linked list which, apart from the normal data they should contain (a pointer to the next element, and a pointer to the previews one), I want them to hold any kind of data, without having to use templates. Why am I obsessed to do it this way? Consider it as a learning procedure. I believe that way I can create an interface similar to the Objective C's NSArray, which is an array that can hold any kind of data (ex. in the first slot, you can have an NSSTring and in the second one you can have an NSDictionary). I may not be able to do it (it's just an idea, after all). Are void pointers the right way to do it? |
Short answer is no. One of the worst possible ways to learn a new programming language is to try to replicate features from another language. And you're trying to learn C++ by replicating a capability of Objective C which C++ is not really designed to support. Similarly, trying to learn Objective C by replicating something like C++ templates would be a poor way to learn Objective C.
That said, there are ways. But they require moderately advanced knowledge of C++, and some other programming methodologies, which you don't yet have. ONLY OBSESSIVE FOOLS WILL READ ON!!!! You're talking about a generic container, with different types of elements able to be placed into one container. Objective C supports that more easily, as all types are derived from a base type (id). In C++, there is no universal base type. The closest you can come would be an array that works with a specific set of types. If those types are only basic types (int, float, pointers, etc) you can employ a union to hold the data, but you also need some other information (eg an enumerated type) to keep track of what data type is actually stored in the union. If the types you want to store include C++ classes, you could do do some hackery with void pointers, and would still need to carry around information about the type of object being stored. And you would need to recompile every time you want to introduce a new type of object into your container (in effect, because a void pointer must be converted into a pointer to the actual type before the actual object can be used). You will find doing the above non-trivial, because C++ isn't really intended to be used for such things: one of the premises of C++ is that a function that receives a generic void pointer KNOWS what conversions are needed before that void pointer can be used. There are some more advanced techniques to do the sort of thing you want (eg a common base class for all types you wish to store in the array; defining such a base class is non-trivial and also gives code maintenance nightmares) or introspection techniques associated with distributed object frameworks (CORBA, DCOM, etc). I would recommend you learn more of the basics of C++ before trying to use such things. |
I didn't try to learn C++ by replicating ObjC's features, or the other way around. It's just a game for me. I know Obj-C very well, believe me. But haven't you ever felt you want to do something just for the sake of doing it?
Anyway, thanks for the advice, and it never hurts asking, so I did. Besides, since I have never been involved with void pointers, it's a good opportunity to do so, even if that's not going to lead into a valid project. I'm 20 years old, I still have time to mess around a little bit. :) EDIT: Quote:
It is simulated anyway into the CoreFoundation Framework by Apple, which, among other things, provides classes that behave like an NSArray. |
Quote:
Quote:
Quote:
So, if you wanted, it is definitely feasible to write a Objective C interpreter/compiler or library in C or C++. What is less feasible is providing equivalent functionality for a C++ programmer which, from your wording, I assumed was what you were about. One characteristic of a C++ compiler is that, at run time, most type information is unavailable. So there is no technique in C++ that allows calling an arbitrary method of an object, given only the name of the method as a string (there are techniques to call specific methods, by use of a map construct, but that relies on entries being explicitly placed in the map before attempting to use it). The core of the difference is that C++ is a statically typed language (meaning that the program cannot directly access, at run time, information about the type of an object or methods it provides) in contrast to Objective C which is dynamically typed (meaning that, given an arbitrary object, information about its type and methods can be queried at run time). Which means that, given an object in an NSArray, it is possible in Objective C to directly access information about the type and methods it supplies. This is not possible, in C++: to simulate such a thing, it is necessary to do lots of extra bookkeeping (of the type information, of information about the methods) and to accept some constraints on ability to do that with some types but not others. |
This is completely possible in a type safe way as long as you know the type of the object you want to get out. Just use Boost.Any, sorry if that is not what is desired here, but with it you can make a type safe generic container. The only problem is Boost.Any can't down cast, so you need the exact type not a base class type, which can be limiting. With Boost.Any there is no need to add fields to a special structure every time you want to use a new type.
(Yeah- I do need more nails for my shiny Boost hammer) |
Quote:
|
| All times are GMT -5. The time now is 1:21 AM. |
Powered by vBulletin® Version 3.7.0, Copyright ©2000 - 2008, Jelsoft Enterprises Ltd.
Copyright ©2007 DaniWeb® LLC