digitalmars.D.learn - void pointer syntax
- Stephen Jones (34/34) May 14 2012 I want an array of different classes of objects. I tried to
- H. S. Teoh (32/38) May 14 2012 [...]
- Stephen Jones (12/54) May 15 2012 Using Object gives exactly the same problem as the Object super
- Chris Cain (20/32) May 15 2012 You'd just try to cast each object into the classes you want.
- =?UTF-8?B?QWxpIMOHZWhyZWxp?= (75/90) May 15 2012 But Object is better than void* because the latter has no safety and
- H. S. Teoh (20/30) May 15 2012 If you did not know what type each object was, how do you know they have
- Stephen Jones (32/78) May 16 2012 Ali you are right about the void pointer requiring a cast as I
- Era Scarecrow (22/34) May 16 2012 But the thing about using an abstract class, and
- dennis luehring (11/12) May 16 2012 just throw aways your sensless void pointer or whatever idea - create a
- Chris Cain (39/50) May 16 2012 I suppose "proper way of doing things" isn't exactly correct.
- dennis luehring (6/6) May 15 2012 Am 14.05.2012 20:40, schrieb Stephen Jones:
I want an array of different classes of objects. I tried to subsume the differences by extending the classes under a single interface/abstract class/super class (3 different approaches) all to no avail as I could not access the public variables of the instantiated classes while storing them in an array defined by the interface/super class. interface Widget{ void draw(); } class Button : Widget{ public int vertCount; void draw(){} } class Cursor : Widget{ public int vertCount; void draw(){} } //called from Widget[] widgets; widgets~=new Button(); widgets~=new Cursor(); foreach(Widget w; widgets){ writeln(w.vertCount); } //Error: no property 'vertCount' for type 'Widget.Widget' A solution that should work is to dump extending the classes and make an array of void pointers that point, some to Button objects and some to Cursors but I do not know the syntax for doing this, or even if it is possible to have an array of pointers pointing at different classes of objects. I should think it should be possible given that, on a 32 bit machine, pointers are all 32 bit ints so it is basically an array of ints that is being created, only those ints contain the address of a bunch of different types of objects.
May 14 2012
On Mon, May 14, 2012 at 08:40:30PM +0200, Stephen Jones wrote:I want an array of different classes of objects. I tried to subsume the differences by extending the classes under a single interface/abstract class/super class (3 different approaches) all to no avail as I could not access the public variables of the instantiated classes while storing them in an array defined by the interface/super class.[...] Every class derives from Object, so an Object[] should do what you want. Also, if you need to access public variables of a derived class, you need to downcast: // Suppose this is your class heirarchy class Base { int x; } class Derived1 : Base { int y; } class Derived2 : Base { int z; } // Here's how you can put derived objects in a single array auto d1 = new Derived1(); auto d2 = new Derived2(); Base[] o = [d1, d2]; // You can directly access base class members: o[0].x = 123; o[1].x = 234; // Here's how to downcast to a derived type Derived1 dp = cast(Derived1) o[0]; if (dp !is null) { dp.y = 345; } Derived2 dp2 = cast(Derived2) o[1]; if (dp2 !is null) { dp.z = 456; } Note that the if statements are necessary, since when downcasting you don't know if the given Base object is actually an instance of that particular derived object. If you tried cast(Derived1) o[1], it will return null because o[1] is not an instance of Derived1. T -- Nothing in the world is more distasteful to a man than to take the path that leads to himself. -- Herman Hesse
May 14 2012
On Monday, 14 May 2012 at 19:04:46 UTC, H. S. Teoh wrote:On Mon, May 14, 2012 at 08:40:30PM +0200, Stephen Jones wrote:Using Object gives exactly the same problem as the Object super class does not have vcount variable. Casting is not a solution because the reason for throwing different sorts of widgets into a single array was so I did not have to track what each type of object was; not tracking what each object in the array is I have no means of knowing what to cast each Widget in the array to. If some one knows void pointer syntax that would be helpful. As I understand it there is a type called size_t that takes the address of as a a value. Can I make an array of these and simply initialize each with &button1, &cursor, etc? Also, how is size_t freed?I want an array of different classes of objects. I tried to subsume the differences by extending the classes under a single interface/abstract class/super class (3 different approaches) all to no avail as I could not access the public variables of the instantiated classes while storing them in an array defined by the interface/super class.[...] Every class derives from Object, so an Object[] should do what you want. Also, if you need to access public variables of a derived class, you need to downcast: // Suppose this is your class heirarchy class Base { int x; } class Derived1 : Base { int y; } class Derived2 : Base { int z; } // Here's how you can put derived objects in a single array auto d1 = new Derived1(); auto d2 = new Derived2(); Base[] o = [d1, d2]; // You can directly access base class members: o[0].x = 123; o[1].x = 234; // Here's how to downcast to a derived type Derived1 dp = cast(Derived1) o[0]; if (dp !is null) { dp.y = 345; } Derived2 dp2 = cast(Derived2) o[1]; if (dp2 !is null) { dp.z = 456; } Note that the if statements are necessary, since when downcasting you don't know if the given Base object is actually an instance of that particular derived object. If you tried cast(Derived1) o[1], it will return null because o[1] is not an instance of Derived1. T
May 15 2012
On Wednesday, 16 May 2012 at 02:01:25 UTC, Stephen Jones wrote:Using Object gives exactly the same problem as the Object super class does not have vcount variable. Casting is not a solution because the reason for throwing different sorts of widgets into a single array was so I did not have to track what each type of object was; not tracking what each object in the array is I have no means of knowing what to cast each Widget in the array to.You'd just try to cast each object into the classes you want. Like he said, it'll be null if the casting failed. Otherwise, it'll be the object and you can get the vcount. However, I have to ask ... is it that all Widgets need to have this vcount? If so, the proper way to do this is user-defined properties: http://dlang.org/property.html So your Widget class might look like this: class Widget { public property int vertCount(); // getter public property int vertCount(int); // setter void draw(){} }If some one knows void pointer syntax that would be helpful. As I understand it there is a type called size_t that takes the address of as a a value. Can I make an array of these and simply initialize each with &button1, &cursor, etc? Also, how is size_t freed?This is _not_ a solution you want at all. Converting pointers to integers in D is undefined behavior and size_t is not a type for that (it's used to hold indices for arrays and such). If you convert a pointer to an int and get rid of the pointer, the Garbage Collector will not see any references to your object anymore and will reap your object.
May 15 2012
On 05/15/2012 07:01 PM, Stephen Jones wrote:Using Object gives exactly the same problem as the Object super class does not have vcount variable.But Object is better than void* because the latter has no safety and completely unusable. All you can do with a void* is to cast it back to its own type. If you don't keep type information somehow, nobody knows what the original type was.Casting is not a solutionThat is the only solution. It may be somehow wrapped, but you must cast void* to a useful type first.because the reason for throwing different sorts of widgets into a single array was so I did not have to track what each type of object was;Yeah, great! That's polymorphism. Great. You keep a Widget[] and use it.not tracking what each object in the array is I have no means of knowing what to cast each Widget in the array to.Exactly! :) Either you or the compiler must keep track of it. void* removes any trace of type information.If some one knows void pointer syntax that would be helpful.import std.stdio; void main() { int i; double d; void*[] array; array ~= cast(void*)&i; array ~= cast(void*)&d; foreach (address; array) { writeln("I don't know what type of object is at ", address); } }As I understand it there is a type called size_t that takes the address of as a a value.No. size_t is suitable to represent concepts like size, quantity, etc. Concepts that are supposed to be never less than zero.Can I make an array of these and simply initialize each with &button1, &cursor, etc? Also, how is size_t freed?You can but it would make no sense: import std.stdio; void main() { int i; double d; size_t[] array; array ~= cast(size_t)&i; array ~= cast(size_t)&d; foreach (size; array) { writeln("I don't know what to do with this amount: ", size); } } Getting back to your original question, here is another solution where Widget is a class (not an interface) that has a vertCount member. It makes it necessary that the subclasses construct it with that information: import std.stdio; class Widget{ abstract void draw(); size_t vertCount; this(size_t vertCount) { this.vertCount = vertCount; } } class Button : Widget{ override void draw(){} this() { super(100); } } class Cursor : Widget{ override void draw(){} this() { super(200); } } void main() { Widget[] widgets; widgets~=new Button(); widgets~=new Cursor(); foreach(Widget w; widgets){ writeln(w.vertCount); } } Ali -- D Programming Language Tutorial: http://ddili.org/ders/d.en/index.html
May 15 2012
On Wed, May 16, 2012 at 04:01:23AM +0200, Stephen Jones wrote: [...]Using Object gives exactly the same problem as the Object super class does not have vcount variable. Casting is not a solution because the reason for throwing different sorts of widgets into a single array was so I did not have to track what each type of object was; not tracking what each object in the array is I have no means of knowing what to cast each Widget in the array to.If you did not know what type each object was, how do you know they have a vcount variable? If you _do_ know that they have a vcount variable, that means you know what type to downcast to. If there is more than one subclass with a vcount variable, that's an indication that you want to factor it into a common base class that gives a unified access to it, in which case you'd downcast to the common base class.If some one knows void pointer syntax that would be helpful. As I understand it there is a type called size_t that takes the address of as a a value. Can I make an array of these and simply initialize each with &button1, &cursor, etc? Also, how is size_t freed?Void pointer does not help you at all. You can't access the vcount variable through a void pointer unless you know it's a particular type that has such a variable -- you'd have to cast the void pointer to that type first. And in that case, you might as well be downcasting instead because it's type-safe. Blindly casting a void pointer into a particular type because you _think_ that's what it is, is a recipe for disaster when later on your list changes and the void pointer no longer points to what you think it points to. T -- If lightning were to ever strike an orchestra, it'd always hit the conductor first.
May 15 2012
On Wednesday, 16 May 2012 at 02:55:41 UTC, H. S. Teoh wrote:On Wed, May 16, 2012 at 04:01:23AM +0200, Stephen Jones wrote: [...]Ali you are right about the void pointer requiring a cast as I figured out. It does seem kind of odd that you cannot keep an array of integers that hold the start address of blocks of memory which blocks of memory contain objects such as Buttons etc. For I would have thought that the start address would hold something akin to a header telling whoever pointed at it that it was of a type, whichever type it was. And that if somebody asked for a piece of data that was in that block of memory the header would provide the index to it. But then I have to speculate about how it is things work because compiler design is not a field I am familiar with. Ali your post above, and T your post in the other forum (Simpsons bit) is sort of what I was after. I tried both interface and abstract class but not outright super class. The problem I have with the solution is the same problem I have with header files and cpp files; in both instances you need to hunt in other files for the variable's definition. If name is a field that will contain Bart's name then it should be in the Bart class, otherwise I end up wasting time confused about some variable that has been initialized or used to initialize some other variable and not finding it in the relevant module. Cain: My understanding is that D is based on "no proper ways of doing things" just get the job done. The use of properties when you can use public access baffles me. So long as you are careful with the namespaces why would you want to incur function overheads that could only possibly "save" the situation if you were not careful with namespaces? Another anomaly I have never understood is why would you use multiple property calls when you could use a single function to set or get multiple items of data for the cost of a single function? It is either fashion, politics, or I am missing some piece of the puzzle.Using Object gives exactly the same problem as the Object super class does not have vcount variable. Casting is not a solution because the reason for throwing different sorts of widgets into a single array was so I did not have to track what each type of object was; not tracking what each object in the array is I have no means of knowing what to cast each Widget in the array to.If you did not know what type each object was, how do you know they have a vcount variable? If you _do_ know that they have a vcount variable, that means you know what type to downcast to. If there is more than one subclass with a vcount variable, that's an indication that you want to factor it into a common base class that gives a unified access to it, in which case you'd downcast to the common base class.If some one knows void pointer syntax that would be helpful. As I understand it there is a type called size_t that takes the address of as a a value. Can I make an array of these and simply initialize each with &button1, &cursor, etc? Also, how is size_t freed?Void pointer does not help you at all. You can't access the vcount variable through a void pointer unless you know it's a particular type that has such a variable -- you'd have to cast the void pointer to that type first. And in that case, you might as well be downcasting instead because it's type-safe. Blindly casting a void pointer into a particular type because you _think_ that's what it is, is a recipe for disaster when later on your list changes and the void pointer no longer points to what you think it points to. T
May 16 2012
On Wednesday, 16 May 2012 at 11:12:19 UTC, Stephen Jones wrote:Ali your post above, and T your post in the other forum (Simpsons bit) is sort of what I was after. I tried both interface and abstract class but not outright super class. The problem I have with the solution is the same problem I have with header files and cpp files; in both instances you need to hunt in other files for the variable's definition. If name is a field that will contain Bart's name then it should be in the Bart class, otherwise I end up wasting time confused about some variable that has been initialized or used to initialize some other variable and not finding it in the relevant module.But the thing about using an abstract class, and polymorphism/inheritance is the known interface is whatever the object is cast to. So the Simpson family you only know about string name, and object; That meaning anything that bart may have otherwise isn't accessible since that part of the code doesn't know more than what the Simpson class lets it know ahead of time. That is it. There isn't that much to look up depending on how high up/down you go. But I do hate looking up the information too..Cain: My understanding is that D is based on "no proper ways of doing things" just get the job done.I thought that was C++.... it was something like 'refuse to give in to an ounce of better control or simplicity if it may have any impact on performance and zero overhead'.... plus backwards compatibility. Besides the STL is so confusing I will likely never use it or most of C++. Proper ways of doing things are more how you write your code rather than the language. immutable, string, shared, scope... All these things have a 'proper way' of using them if you look. Just having an array as a fat pointer (with length) is a huge improvement that's built into the language. It's almost more 'D is so new that the proper way to make use of it isn't fully written/available'.
May 16 2012
Am 16.05.2012 13:12, schrieb Stephen Jones:just throw aways your sensless void pointer or whatever idea - create a base interface or better base-class - everything else is just damn wrong btw: all oop widget sets for c++, java or else are haveing a widget base class that works like people telling you - try looking at Qt, QWidget, Forms whatever baseclass all you need to do is to have a common interface - thats OOP all about, if you interested (or think you need to) get into implementation details of derived classe means you don't do OOP and then you need to do casting and all this strange looking stuff - but that will also happen in every other language around - because you do/think of OOP in a wrong way
May 16 2012
On Wednesday, 16 May 2012 at 11:12:19 UTC, Stephen Jones wrote:Cain: My understanding is that D is based on "no proper ways of doing things" just get the job done. The use of properties when you can use public access baffles me. So long as you areI suppose "proper way of doing things" isn't exactly correct. There's always many ways of doing things, for instance, everyone else was suggesting a super class, which is also a correct way of doing things. Usually in most languages when you're designing an interface to something, you specify getter and setter functions because it's a better way of encapsulating the functionality of a class.careful with the namespaces why would you want to incur function overheads that could only possibly "save" the situation if you were not careful with namespaces? AnotherI think this is precisely the situation most are talking about when they say "premature optimization." You're worried about the overhead of a function call on something that I would suspect (with good reason) will not take up more than 1% of your processing time. You should worry about the function overhead on something like a double or triple nested loop on your main algorithm.anomaly I have never understood is why would you use multiple property calls when you could use a single function to set or get multiple items of data for the cost of a single function? It is either fashion, politics, or I am missing some piece of the puzzle.Probably mainly experience that stuff like that can be problematic for others (and you, if you come back to it later) to read. Sure, if it makes sense (like "setPosition(123.3, 563.1)" where you can easily deduce that it's putting it at x=123.3 and y=563.1) then setting or getting multiple items of data is fine. You could use something like a struct to represent a collection of data like this and still maintain readability. The thing you really have to understand, though, is that people don't care about it for three reasons: 1. function calls encapsulate functionality and completely avoid problems like you're having. 2. It's already ridiculously fast. Generally speaking, function calls will not be the thing slowing your program down. Especially if you don't even know how much time your code takes as is. 3. Generally programmer time is much more expensive than computation time. For instance, do you honestly think a programmer could spare as much time as you've taken trying to figure out how to save the cost of a few function calls when he has to get this stuff done? The beauty of using properties is that you can mostly work your application like it's setting the variables directly. If later on you decide you _need_ it to directly set the variables, you _could_ just change the interface to the super class solution to expose the bare variables.
May 16 2012
Am 14.05.2012 20:40, schrieb Stephen Jones: Ali Çehreli post got your answer - see the last example of the post news://news.digitalmars.com:119/jov3gn$2vtg$1 digitalmars.com but first: try to understand how the base-class, interface stuff realy works - you will got the same problems in every other language like
May 15 2012