initiating a 2d array of a class

Discussion in 'C++' started by Mark, Nov 11, 2005.

  1. Mark

    Mark Guest

    uhhmmm... not really sure how to word this.
    i cant get get this to compile.. i'm not sure what the proper syntax to
    do this is.. hopefully it's self explanatory.

    here's my class:
    ------
    class TileMap
    {
    public:

    int xw, yw;
    int tw, th;
    int rows, cols;
    int fullrows, fullcols;
    int minX, minY, maxX, maxY;

    TileMapCell **grid;

    TileMap(int rows, int cols, int xw, int yw) : rows(rows),
    cols(cols), xw(xw), yw(yw)
    {
    tw = xw*2;
    th = yw*2;
    fullrows = rows+2;
    fullcols = cols+2;
    minX = tw;
    minY = th;
    maxX = tw + (rows*tw);
    maxY = th + (rows*th);
    }

    TileMapCell GetTile_S(int x, int y)
    {
    return grid[int(x/tw)][int(y/th)];
    }

    TileMapCell GetTile_V(Vector2 v)
    {
    return grid[int(v.x/tw)][int(v.y/th)];
    }

    TileMapCell GetTile_I(int x, int y)
    {
    return grid[x][y];
    }

    void GetIndex_S(Vector2 v, int x, int y)
    {
    v.x = int(x/tw);
    v.y = int(y/th);
    }

    void GetIndex_V(Vector2 v, Vector2 p)
    {
    v.x = int(p.x/tw);
    v.y = int(p.y/th);
    }

    void Building()
    {
    int x = xw;
    int y = yw;
    int fullrows = fullrows;//the ACTUAL size of the grid, including
    border tiles
    int fullcols = fullcols;
    int rows = rows;
    int cols = cols;

    //build raw tiles
    for(int i = 0; i < fullrows; i++)
    {
    grid = new TileMapCell[fullcols]; // <--- need help here!!!
    for(int j = 0; j < fullcols; j++)
    {
    grid[j] = new TileMapCell(i,j,x,y,xw,yw);
    y += th;
    }
    x += tw;
    y = yw;
    }
    }
    };
    --------------------
    the problem is in here:
    ------------------
    //build raw tiles
    for(int i = 0; i < fullrows; i++)
    {
    grid = new TileMapCell[fullcols]; // <--- need help here!!!
    for(int j = 0; j < fullcols; j++)
    {
    grid[j] = new TileMapCell(i,j,x,y,xw,yw);
    y += th;
    }
    x += tw;
    y = yw;
    }
    -----------------
    and incase you were about to ask:
    ------------
    class TileMapCell
    {
    public:

    int ID;
    int CTYPE;
    int i,j; // index of tile in grid

    TileMapCell *nU, *nD, *nL, *nR; // neighboring tiles
    int eU, eD, eL, eR; // edge info

    float gx; // environmental properties
    float gy;
    float d;

    TileMapCell *next, *prev;

    Vector2 pos;

    int xw, yw;

    float minx, maxx, miny, maxy;

    int signx, signy, sx, sy;

    TileMapCell(int i, int j, float x, float y, int xw, int yw) : i(i),
    j(j), xw(xw), yw(yw)
    {
    pos.set(x,y);

    gx = 0;
    gy = GRAV;
    d = DRAG;

    nU = nD = nL = nR = NULL;
    eU = eD = eL = eR = EID_OFF;
    next = prev = NULL;

    minx = pos.x - xw;
    maxx = pos.x + xw;
    miny = pos.y - yw;
    maxy = pos.y + yw;

    signx = signy = sx = sy = 0;
    }

    void LinkU(TileMapCell *t)
    {
    nU = t;
    }
    void LinkD(TileMapCell *t)
    {
    nD = t;
    }
    void LinkL(TileMapCell *t)
    {
    nL = t;
    }
    void LinkR(TileMapCell *t)
    {
    nR = t;
    }
    };
    -------------------
    and before you tell me

    grid = new TileMapCell[fullcols];

    doesnt work because there is no TileMapCell() constructor.... I know.
    but it shouldnt really be constructing anything at that point... right?

    if you need more info.. just leave a message.

    thanks for the help.
     
    Mark, Nov 11, 2005
    #1
    1. Advertising

  2. Mark wrote:
    ....
    > and before you tell me
    >
    > grid = new TileMapCell[fullcols];
    >
    > doesnt work because there is no TileMapCell() constructor.... I know.
    > but it shouldnt really be constructing anything at that point... right?
    >
    > if you need more info.. just leave a message.


    It appears you want to create an array of pointers to

    TileMapCell.grid = new TileMapCell*[fullcols];
     
    Gianni Mariani, Nov 11, 2005
    #2
    1. Advertising

  3. Mark

    Mark Guest

    hmm..?

    thanks for the fast reply... but that doesn't make any sense...

    basically if # represents a cell, if my understanding is correct, then
    grid would represent

    #
    #
    #
    #
    ....

    and we want to add some cells to the x dimension...

    ###
    ###
    ###
    ###
    ....

    but what you're saying is we add a 2D something or other ( *[] ) to
    each row??


    anyways.. i tried that, and

    grid = new TileMapCell*[fullcols]; // <--- need help here!!!

    doesnt compile either.
    says:
    cannot convert `TileMapCell**' to `TileMapCell*' in assignment

    so like i said.. its trying to turn something with 2 dimensions into
    something with 1...
     
    Mark, Nov 11, 2005
    #3
  4. * Mark:
    > uhhmmm... not really sure how to word this.
    > i cant get get this to compile.. i'm not sure what the proper syntax to
    > do this is.. hopefully it's self explanatory.


    Solution: use standard library classes, and use the Boost library, and
    _don't_ do raw arrays or raw pointers.



    > here's my class:
    > ------
    > class TileMap
    > {
    > public:
    >
    > int xw, yw;
    > int tw, th;
    > int rows, cols;
    > int fullrows, fullcols;
    > int minX, minY, maxX, maxY;


    Surely you don't want the above members public. Make them private.


    > TileMapCell **grid;


    Go to <url: http://www.boost.org/libs/multi_array/doc/user.html>.

    Hth.,

    - Alf

    --
    A: Because it messes up the order in which people normally read text.
    Q: Why is it such a bad thing?
    A: Top-posting.
    Q: What is the most annoying thing on usenet and in e-mail?
     
    Alf P. Steinbach, Nov 11, 2005
    #4
  5. Mark

    David White Guest

    I haven't looked through your code at all. I've only tried to compile it
    (after making various repairs), and there appears to be two main problems:
    1. Class TileMapCell does not have a default constructor, so you cannot
    create an array of them.
    i.e., grid = new TileMapCell[fullcols];

    2. Your types don't match in: grid[j] = new TileMapCell(i,j,x,y,xw,yw);
    If grid is TileMapCell**, then grid is TileMapCell* and grid[j] is a
    TileMapCell object, but "new TileMapCell(i,j,x,y,xw,yw);" returns
    TileMapCell*, so you are trying to convert a pointer into an actual object,
    which of course doesn't work. Assuming that your pointers are valid, try
    this instead: grid[j] = TileMapCell(i,j,x,y,xw,yw);
    Not that that will create a temporary TileMapCell to which the array element
    will be assigned and then the temporary will be destroyed.

    It might be worth remembering that you don't have to use 'new' to create
    everything. In fact, it's best to avoid it whenever you reasonably can.

    DW
     
    David White, Nov 11, 2005
    #5
  6. Mark

    David White Guest

    "David White" <> wrote in message
    news:kuVcf.309$...
    > Not that that will create a temporary TileMapCell to which the array

    element

    Was meant to be: _Note_ that...

    DW
     
    David White, Nov 11, 2005
    #6
  7. Mark

    Mark Guest

    David White wrote:
    > 1. Class TileMapCell does not have a default constructor, so you cannot
    > create an array of them.
    > i.e., grid = new TileMapCell[fullcols];


    Mark wrote:
    > doesnt work because there is no TileMapCell() constructor.... I know.
    > but it shouldnt really be constructing anything at that point... right?


    David White wrote:
    > It might be worth remembering that you don't have to use 'new' to create
    > everything. In fact, it's best to avoid it whenever you reasonably can.


    I'll try removing the "new"... but uhm... I don't think it complains
    about that line.

    I believe I've done something like this before... I guess I'll have to
    dig through my old code.

    Alf P. Steinbach wrote:
    > Go to <url: http://www.boost.org/libs/multi_array/doc/user.html>.


    I hate using those crazy libraries where it isn't necessary...
    sure, *maybe* they can make some things easier... but their syntax is
    nuts, and they have all this extra unecessary baggage. there is a way
    to do it...

    like, what is all this crap just to create a 3d array?

    typedef boost::multi_array<double, 3> array_type;
    typedef array_type::index index;
    array_type A(boost::extents[3][4][2]);

    and what benefits does it even have??

    i guess i'd have to look into it before i bash it, but i'm not looking
    for extra features anyway.

    but yes, thanks... i shall, give this a shot if worse comes to worse.

    > Surely you don't want the above members public. Make them private.


    well. sure i do. why not?

    the only reason i can see for *not* having them public is so that one
    doesn't "accidentally" change their values.
    but the only person who is going to be using this class is me.
    and i'd like to easily read and modify them without having to make 20
    different "getters" and "setters"
    especially for debugging purposes...

    i don't see why people always insist that the majority of members are
    private. there's no real point unless you are going to publicly
    distribute it....

    not to critique your post or anything :D i appreciate your help.
    (btw, if you can give me a better reason, i'm all ears. i'm open
    minded, but that's the way i see it as of now)
     
    Mark, Nov 11, 2005
    #7
  8. * Mark:
    > * Alf P. Steinbach:
    > >
    > > Go to <url: http://www.boost.org/libs/multi_array/doc/user.html>.

    >
    > I hate using those crazy libraries where it isn't necessary...
    > sure, *maybe* they can make some things easier... but their syntax is
    > nuts, and they have all this extra unecessary baggage. there is a way
    > to do it...


    Boost is very far from being a crazy library. Many parts of Boost are
    slated for inclusion in the standard library with the next version of
    the C++ standard. Those parts include fixed size arrays, but currently
    not the multi-dimensional arrays.


    > like, what is all this crap just to create a 3d array?
    >
    > typedef boost::multi_array<double, 3> array_type;
    > typedef array_type::index index;
    > array_type A(boost::extents[3][4][2]);
    >
    > and what benefits does it even have??


    Those three lines do all that you're (unsuccessfully) trying to do in
    umpteen lines of code, and the Boost code has been subjected to rigorous
    review so that you can trust it.

    But feel free to prefer weeks of debugging instead.


    > i guess i'd have to look into it before i bash it, but i'm not looking
    > for extra features anyway.
    >
    > but yes, thanks... i shall, give this a shot if worse comes to worse.
    >
    > > Surely you don't want the above members public. Make them private.

    >
    > well. sure i do. why not?
    >
    > the only reason i can see for *not* having them public is so that one
    > doesn't "accidentally" change their values.
    > but the only person who is going to be using this class is me.
    > and i'd like to easily read and modify them without having to make 20
    > different "getters" and "setters"


    Providing "getters" and "setters" is not just just as bad, it's even
    worse.

    Make those members private and _keep_ them private.

    No per member getters, no per member setters: the client code should not
    have to know anything about the internal members, or whether you have
    implemented your class by having it communicate with a matrix-savvy
    chimpanzee who holds the state -- for example.


    > especially for debugging purposes...
    >
    > i don't see why people always insist that the majority of members are
    > private. there's no real point unless you are going to publicly
    > distribute it....


    It saves you work.

    --
    A: Because it messes up the order in which people normally read text.
    Q: Why is it such a bad thing?
    A: Top-posting.
    Q: What is the most annoying thing on usenet and in e-mail?
     
    Alf P. Steinbach, Nov 11, 2005
    #8
  9. Mark

    David White Guest

    "Mark" <> wrote in message
    news:...
    > David White wrote:
    > > 1. Class TileMapCell does not have a default constructor, so you cannot
    > > create an array of them.
    > > i.e., grid = new TileMapCell[fullcols];

    >
    > Mark wrote:
    > > doesnt work because there is no TileMapCell() constructor.... I know.
    > > but it shouldnt really be constructing anything at that point... right?


    Wrong. You are trying to create an array of TileMapCell objects. That's what
    the 'new' expression is doing. You can't have an object array that doesn't
    contain any objects yet (using conventional means, anyway), if that's what
    you were hoping for.

    If you want to have (in effect) a 2D array of TileMapCells but you don't
    want to default-construct them initially and replace them with variably
    constructed ones later, and you do want to persist with bare pointers to
    contain them, then you can use more indirection:
    TileMapCell ***grid;
    ....
    grid = new TileMapCell**[fullrows];
    for(int i = 0; i < fullrows; i++)
    {
    grid = new TileMapCell*[fullcols];
    for(int j = 0; j < fullcols; j++)
    {
    grid[j] = new TileMapCell(i,j,x,y,xw,yw);
    ....

    (Don't forget to delete all objects and pointer arrays when you are done
    with them; requires nested loops also).

    If this doesn't look more appealing than what you already have, then fix
    what you have according to my first reply, or, as has been wisely suggested
    elsewhere, use a proper container that does all the messy memory management
    for you.

    BTW, to illustrate how fraught it can be to work with umpteen pointers
    several nestings deep, your original code disastrously omits this crucial
    line before the loops:
    grid = new TileMapCell*[fullrows];

    > I'll try removing the "new"... but uhm... I don't think it complains
    > about that line.


    Humour me and try compiling it again, but this time include a default
    constructor so the earlier line compiles.

    DW
     
    David White, Nov 11, 2005
    #9
  10. Mark

    Neil Cerutti Guest

    On 2005-11-11, Mark <> wrote:
    > uhhmmm... not really sure how to word this.
    > i cant get get this to compile.. i'm not sure what the proper syntax to
    > do this is.. hopefully it's self explanatory.
    >
    > here's my class:
    > ------
    > class TileMap
    > {
    > public:
    >
    > int xw, yw;
    > int tw, th;
    > int rows, cols;
    > int fullrows, fullcols;
    > int minX, minY, maxX, maxY;
    >
    > TileMapCell **grid;


    That's a bewildering schmorgasbord of public variables. If
    they're meant to be manipulated and viewed by users, you should
    probably use better names, or at least document them.

    My guess is you don't need any of them except for rows, cols, and
    grid.

    If you're going to make everything in a class public (and
    actually you shouldn't), just use a struct.

    > TileMap(int rows, int cols, int xw, int yw) : rows(rows),
    > cols(cols), xw(xw), yw(yw)
    > {
    > tw = xw*2;
    > th = yw*2;
    > fullrows = rows+2;
    > fullcols = cols+2;
    > minX = tw;
    > minY = th;
    > maxX = tw + (rows*tw);
    > maxY = th + (rows*th);
    > }


    You could've initialized all of those members in the
    initialization list.

    Finally, you initialized everything except grid, which is the one
    you'd ideally like to see initialized in the constructor.

    >
    > TileMapCell GetTile_S(int x, int y)
    > {
    > return grid[int(x/tw)][int(y/th)];
    > }
    >
    > TileMapCell GetTile_V(Vector2 v)
    > {
    > return grid[int(v.x/tw)][int(v.y/th)];
    > }
    >
    > TileMapCell GetTile_I(int x, int y)
    > {
    > return grid[x][y];
    > }
    >
    > void GetIndex_S(Vector2 v, int x, int y)
    > {
    > v.x = int(x/tw);
    > v.y = int(y/th);
    > }
    >
    > void GetIndex_V(Vector2 v, Vector2 p)
    > {
    > v.x = int(p.x/tw);
    > v.y = int(p.y/th);
    > }


    I'm assuming Vector2 is a reference type, or those functions do
    nothing.

    > void Building()


    You probably ought to call this function in the constructor. Or
    move this code there.

    > {
    > int x = xw;
    > int y = yw;
    > int fullrows = fullrows;//the ACTUAL size of the grid, including
    > border tiles
    > int fullcols = fullcols;
    > int rows = rows;
    > int cols = cols;


    The British are comin'! Hide the yer women, children an' member
    names! ;-)


    You must initialize grid before proceeding.

    grid = new (TileMapCell*)[fullrows];

    Then proceed to initialize those pointers.


    > //build raw tiles
    > for(int i = 0; i < fullrows; i++)
    > {
    > grid = new TileMapCell[fullcols]; // <--- need help here!!!


    Needs a default constructor.

    > for(int j = 0; j < fullcols; j++)
    > {
    > grid[j] = new TileMapCell(i,j,x,y,xw,yw);
    > y += th;
    > }
    > x += tw;
    > y = yw;
    > }
    > }
    > };


    Here's how it might look:

    grid = new (TileMapCell*)[fullrows];
    for (int i = 0; i < fullrows; ++i)
    {
    /* Hint: Won't work without a default constructor for
    * TileMapCell. Constructs an array of TileMapCells. You'll
    * need a different grid data type if you want to avoid the
    * default construction, e.g., pointer to pointer to grid */
    grid = new TileMapCell[fullcols];
    for (int j = 0; j < fullcols; ++j)
    {
    /* Assign the correct values to the members of the default
    * constructed TileMapCell instances. */
    grid[j].i = i;
    grid[j].j = j;
    /* etc. */
    }
    }

    > and incase you were about to ask:


    No way. I can't watch any more. ;-)

    > grid = new TileMapCell[fullcols];
    >
    > doesnt work because there is no TileMapCell() constructor.... I
    > know. but it shouldnt really be constructing anything at that
    > point... right?


    No, you're asking new to create an array of objects. Those
    objects must be constructed.

    --
    Neil Cerutti
     
    Neil Cerutti, Nov 11, 2005
    #10
  11. Mark

    Neil Cerutti Guest

    On 2005-11-11, Neil Cerutti <> wrote:
    > On 2005-11-11, Mark <> wrote:
    > grid = new (TileMapCell*)[fullrows];
    > for (int i = 0; i < fullrows; ++i)
    > {
    > /* Hint: Won't work without a default constructor for
    > * TileMapCell. Constructs an array of TileMapCells. You'll
    > * need a different grid data type if you want to avoid the
    > * default construction, e.g., pointer to pointer to grid */


    I meant "pointer to pointer to pointer to grid" there.


    --
    Neil Cerutti
     
    Neil Cerutti, Nov 11, 2005
    #11
  12. Mark

    Neil Cerutti Guest

    On 2005-11-11, Neil Cerutti <> wrote:
    > On 2005-11-11, Neil Cerutti <> wrote:
    >> On 2005-11-11, Mark <> wrote:
    >> grid = new (TileMapCell*)[fullrows];
    >> for (int i = 0; i < fullrows; ++i)
    >> {
    >> /* Hint: Won't work without a default constructor for
    >> * TileMapCell. Constructs an array of TileMapCells. You'll
    >> * need a different grid data type if you want to avoid the
    >> * default construction, e.g., pointer to pointer to grid */

    >
    > I meant "pointer to pointer to pointer to grid" there.


    Arrgh! No I didn't.

    --
    Neil Cerutti
     
    Neil Cerutti, Nov 11, 2005
    #12
  13. Mark

    Default User Guest

    Alf P. Steinbach wrote:


    > Boost is very far from being a crazy library. Many parts of Boost are
    > slated for inclusion in the standard library with the next version of
    > the C++ standard. Those parts include fixed size arrays, but
    > currently not the multi-dimensional arrays.


    Which makes them third-party libraries at this point. No one should be
    forced to use them if they don't want to.


    Brian

    --
    Please quote enough of the previous message for context. To do so from
    Google, click "show options" and use the Reply shown in the expanded
    header.
     
    Default User, Nov 11, 2005
    #13
  14. Mark

    Kai-Uwe Bux Guest

    Default User wrote:

    > Alf P. Steinbach wrote:
    >
    >
    >> Boost is very far from being a crazy library. Many parts of Boost are
    >> slated for inclusion in the standard library with the next version of
    >> the C++ standard. Those parts include fixed size arrays, but
    >> currently not the multi-dimensional arrays.

    >
    > Which makes them third-party libraries at this point. No one should be
    > forced to use them if they don't want to.


    And who exactly is forcing someone here to use them? All that happened is:

    a) Alice asked "how do you solve problem X"?
    b) Bob answered "use boost::...".
    c) Alice said: I don't like that.

    Now, if Alice is arbitrarily restricting the search space for solutions to
    the problem, Bob might be less willing to lend a helping hand. But that is
    far from forcing.


    Best

    Kai-Uwe
     
    Kai-Uwe Bux, Nov 12, 2005
    #14
  15. Mark

    Mark Guest

    woah.. that's a lot to respond to.. so i'm not going to quote you all,
    but in kind of a collective response...

    uhhhmmm.. ok, so it's evident i *do* need a default constructor with
    the way i was trying to write it.. but, in that case, i guess i wrote
    it completely wrong :)

    yes, the code is kind of messy at this point.. but i just want it to
    run at this point, then i'll clean it up. this is called the "learning
    process" :)

    i've tried lots of approaches.. tried keeping the code all clean and
    such..but eventually you run into a snag, and it all goes to hell.

    so, Alf P. Steinbach, you do make boost sound more appealing.

    but.. i still think the best way to solve a problem, is to understand
    the problem. in other words, sure, i might be able to get away with
    using boost... but how do i know what the heck boost is doing? if i
    *try* to write the code myself, i might get an understanding of how
    boost, and other container classes work, which puts me in a better
    position to solve and tackle future problems. i like to write as much
    as i possibly can by hand...

    i like Neil Cerutti's solution best.. it's clear, and somewhat simple
    :p

    and uhm.. yes.. i intend on calling "Building" inside the
    constructor... i'm actually attempting to follow some code written in
    Flash's ActionScript... so i'm writing it as similar as possible, but
    in C++ of course. Building() will be about 9 times as long as it is
    now....

    ... and what does all this junk do? eventually, it might produce some
    nice 2d collision detection. with slopes, and semi circles, and all
    that fun stuff.

    thanks for all your help guys :) really appreciate it.
     
    Mark, Nov 14, 2005
    #15
  16. Mark

    Mark Guest

    tada... my new solution.
    ----
    grid = new TileMapCell*[fullrows];
    for(int i = 0; i < fullrows; i++)
    {
    grid = new TileMapCell[fullcols];
    for(int j = 0; j < fullcols; j++)
    {
    grid[j].set(i,j,x,y,xw,yw);
    y += th;
    }
    x += tw;
    y = yw;
    }
    -----
    it compiles at least :)
     
    Mark, Nov 14, 2005
    #16
  17. Mark

    David White Guest

    [OT] Collision detection

    Mark wrote:
    > .. and what does all this junk do? eventually, it might produce some
    > nice 2d collision detection. with slopes, and semi circles, and all
    > that fun stuff.


    I don't know whether it's applicable in your case, but collisions can
    detected mathematically, at least in some cases. I wrote a program for fun a
    long time ago that had two "spheres" (really circles) on the screen moving
    around and bouncing off the edges of the screen and off each other,
    according to Newtonian physics. Given the radii, positions and velocities of
    the circles, the collision point, if any, could be found precisely by
    solving a very long quadratic equation.

    DW
     
    David White, Nov 14, 2005
    #17
  18. Mark

    Mark Guest

    Re: Collision detection

    hm.. well it's easy to detect if two circles are overlapping.. but to
    have them react appropriately is much more difficult.
    anyways... i have all the code here.. except in actionscript. but
    proper tutorials shouldnt be hard to come by either...

    but uhm...
    ---
    //build raw tiles
    grid = new TileMapCell*[fullrows];
    for(int i = 0; i < fullrows; i++)
    {
    grid = new TileMapCell[fullcols];
    for(int j = 0; j < fullcols; j++)
    {
    grid[j].Init(i,j,x,y,xw,yw);
    y += th;
    }
    x += tw;
    y = yw;
    }
    ---

    doesnt run so well after all. Init(...) never does get called.....
    crashes somewhere inbetween.

    erm.. dare i ask for suggestions?
     
    Mark, Nov 15, 2005
    #18
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Jay
    Replies:
    8
    Views:
    6,685
    livshitz
    Jun 12, 2011
  2. Pavils Jurjans

    ASP page initiating complex code execution

    Pavils Jurjans, Feb 3, 2004, in forum: ASP .Net
    Replies:
    1
    Views:
    375
    Tommy
    Feb 3, 2004
  3. Replies:
    1
    Views:
    369
    souri challa
    Jul 8, 2005
  4. Replies:
    2
    Views:
    373
  5. John
    Replies:
    2
    Views:
    2,014
    Mark Newmister
    Feb 28, 2006
Loading...

Share This Page