#24180 - DialogPimp - Thu Jul 29, 2004 7:12 am
...is not allowed.
As my brain has collapsed for the day, how would I get around my requirement of having a C++ class-member being able to point to different structures that have been declared as const ?
In a nutshell I have a bunch of const structures describing various animation states and frames, and I want my pointer to point to the current "active state", which naturally changes in response to player input (move left, move right, climb ladder etc).
#24181 - abilyk - Thu Jul 29, 2004 7:23 am
In C, at least (so I assume C++ as well), just use a cast.
Code: |
const u16 my_variable;
u16* my_ptr;
void function()
{
my_ptr = (u16)my_variable;
} |
#24182 - MumblyJoe - Thu Jul 29, 2004 7:53 am
Exerpt from the Borland C++ docs:
Code: |
Category
C++-Specific Keywords
Syntax
const_cast< T > (arg)
Description
Use the const_cast operator to add or remove the const or volatile modifier from a type.
In the statement, const_cast< T > (arg), T and arg must be of the same type except for const and volatile modifiers. The cast is resolved at compile time. The result is of type T. Any number of const or volatile modifiers can be added or removed with a single const_cast expression.
A pointer to const can be converted to a pointer to non-const that is in all other respects an identical type. If successful, the resulting pointer refers to the original object.
A const object or a reference to const cast results in a non-const object or reference that is otherwise an identical type.
The const_cast operator performs similar typecasts on the volatile modifier. A pointer to volatile object can be cast to a pointer to non-
volatile object without otherwise changing the type of the object. The result is a pointer to the original object. A volatile-type object or a reference to volatile-type can be converted into an identical non-volatile type. |
Edit: Just thought I would point out that the compiler will not fold values in at compile-time for a const object that is casted to non-const.
So if you do this:
Code: |
const int ahar = 10;
int* pahar = const_cast<int>(ahar); |
The compiler will not fold 10 into places where you use ahar, it just assumes you know what you are doing and that you are only using the const modifier to be type safe or something.
_________________
www.hungrydeveloper.com
Version 2.0 now up - guaranteed at least 100% more pleasing!
#24191 - DialogPimp - Thu Jul 29, 2004 11:29 am
Geez I embarrass myself sometimes. Why I didn't just try casting it I'll never know. My only consolation is I discussed this with a senior software engineer at work and he didn't have any answers either. Being as dumb as this when I'm paid to write code every day makes me wonder whether I should be mowing lawns for a job ;)
Thanks for your help again guys.
#24207 - sajiimori - Thu Jul 29, 2004 6:14 pm
You can have a non-const pointer to const data.
Code: |
const int* non_const_ptr_to_const_data;
int* const const_ptr_to_non_const_data;
|
If you find yourself casting away constness, rethink your design.
#24215 - jma - Thu Jul 29, 2004 10:00 pm
sajiimori wrote: |
You can have a non-const pointer to const data.
Code: |
const int* non_const_ptr_to_const_data;
int* const const_ptr_to_non_const_data;
|
|
These statements are exactly the same. There is no difference in the compiler between them. You can place the const operator wherever you want. You can specify as many const operators as you want:
Code: |
const int i = 10;
const const const int x = 20;
int const const *y = &x;
const int **z = &y; |
All of these work on an ANSI C compliant compiler. And there is no difference in their meaning (based on the location of const). The compiler may optionally throw a warning like "multiple type qualifiers used", but it isn't an error.
The only time the position of a 'const' matters is in C++ when declaring function methods for a class (this is done quite often for operator overloading, for example).
Jeff
_________________
massung@gmail.com
http://www.retrobyte.org
#24216 - sajiimori - Thu Jul 29, 2004 10:11 pm
False. Try this code, and note that lines 9 and 11 give errors:
Code: |
void test()
{
int i = 10;
int j = 20;
const int* cip = &i;
int* const cpi = &i;
cip = &j;
cpi = &j;
*cip = 30;
*cpi = 30;
}
|
#24217 - jma - Thu Jul 29, 2004 10:14 pm
Yes and no. I misread your post slightly. I didn't notice that you put the * before the const vs. after the const. That makes a different :)
There is no difference between
const int *
int const *
It all lies in where the * is.
Jeff
_________________
massung@gmail.com
http://www.retrobyte.org
#24218 - sajiimori - Thu Jul 29, 2004 10:19 pm
Heheh... I could equally say that it depends on where the 'const' is, but I'd be saying the same thing!
The way I remember the rule is, "the const goes next to the thing that is const". It goes on the pointer's side if the pointer is const, or on the data type side if the data is const.
#24219 - jma - Thu Jul 29, 2004 10:21 pm
I would normally agree, except for the fact that the const can go anywhere relative to the type and there can be as many as you want. The same isn't true of the *:
* int x; // ack!
int **x != int *x;
But I hear what you're saying ;)
Jeff
_________________
massung@gmail.com
http://www.retrobyte.org
#24232 - DialogPimp - Fri Jul 30, 2004 5:46 am
sajiimori wrote: |
If you find yourself casting away constness, rethink your design. |
I'm more than happy to rethink my design (even though it is all working now) and listen to suggestions. I'll explain what I'm doing...
The purpose is a sprite animation system based around a heirarchy of structures. At the lowest level the "sprite cell" stores a pointer to the GFX data in ROM and it's size. Next level up is the "sprite frame" which stores x & y flip, palette, frame delay/ticks, and a pointer to it's sprite cell. Finally an "anim state" is an array of sprite frames that defines the frames necessary to achieve a particular animation sequence. At the highest level an array of states defines all the possible actions that a particular sprite may undertake. An enumeration of all states provides me with a convenient way to index into the state array.
All of this data is fixed and known at compile time of course and there is no reason why it needs to be in RAM. My sprite class just maintains a pointer to the current state and a pointer to the current frame within that state in order to update the graphics on a frame by frame basis.
So that's it. In response to user input I tell the sprite class to change states from STAND to WALK_R for example. The update method takes care of incrementing the defined frame delay, looping back to the beginning if necessary and then DMA'ing in the appropriate cell of graphics data to VRAM on frame changes.
I got it all working last night to the stage where I have Arthur from Ghosts 'n Goblins sitting on my screen and animating left or right depending on what direction keys I use.
#24233 - sajiimori - Fri Jul 30, 2004 6:39 am
Sounds good to me. Giving your RAM structures pointers to the const data should work fine. Here's one simple approach:
Code: |
struct Sprite
{
const StateArray* states;
int cur_state;
int cur_frame;
const Frame* GetFramePtr() { return states[cur_state][cur_frame]; }
};
|