Sign in to follow this  

Inheritence, Constructors, and Arrays oh my!

This topic is 4106 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Ok, ignore the crappy title. anyways, Ive run into a small problem and I have no idea as to what I did wrong (probably a lot though) Im trying to learn the fundamentals of SDL and C++ so im learning by trial and error. eitherway, here is my issue: I have a constructors for my objects
[SOURCE]
/////////// INITIALIZE THE OBJECT STRUCTURES ///////////
class Object 
{ 
protected: 
int x, y; 
int graphicwidth;
int graphicheight;
int height, width;
int solid;
SDL_Surface *graphic;

public: 
Object(int tempx, int tempy, SDL_Surface *tempgraphic) : x(tempx), y(tempy), graphic(tempgraphic)
{}
~Object();
void step(); 
void draw(); 
void setGraphicHeight(int tempHeigt);
void setGraphicWidth(int tempWidth);
int getGraphicHeight();
int getGraphicWidth();
void setSolid(int tempSolid);
void setX(int tempX);
void setY(int tempY);
int getX();
int getY();
int direction;
void setGraphic(SDL_Surface *graphic);
};
[/SOURCE]
and it works great for the object class. I have two subclasses MasterControl and PlayerBlocks. Now here is where my problems come in, doing research i found that I had to set up the contructors for the subclasses too, not a problem. But here is where my problem comes in, I use an array for my PlayerBlocks objects
[SOURCE]
/////////// CREATE THE OBJECTS /////////// 
PlayerBlocks VerticalBlue[NumberOfBlocks];
MasterControl Master(0,0,NULL);
Object Background(0,0,gfx_background);
Object Titleimage(0,0,gfx_titleimage);
Object Bottomimage(0,233,gfx_bottomimage);
Object TopWall(16,120,gfx_topwall);
Object BottomWall((SCR_H)-16, 120, gfx_bottomwall);
Object LeftWall(120,10, gfx_leftwall);
Object RightWallTop(363, 16, gfx_rightwalltop);
Object RightWallBottom(363,(SCR_H)-(13+RightWallBottom.getGraphicHeight()), gfx_rightwallbottom);
[/SOURCE]
but whenever I try to compile I get an error message stating: "no matching call to PlayerBlocks::PlayerBlocks()" So I tried to change the PlayerBlocks to:
[SOURCE]
/////////// CREATE THE OBJECTS /////////// 
PlayerBlocks VerticalBlue[NumberOfBlocks](0,0,NULL);
[/SOURCE]
and it still has problems error message: "bad array initializer" any ideas on what i did wrong?! thanks psiko

Share this post


Link to post
Share on other sites
Objects in an array can only be constructed via default constructor.
There's no C++ syntax allowing you to use other constructors, pass any parameters, etc.

Possibilities:

1. Provide (and use) default constructor and initialize the objects by hand with some function. You're doing something similar already, so it should be of no problem.

2. Use array of pointers:
PlayerBlocks* VerticalBlue[NumberOfBlocks];
for (int i=0; i<NumberOfBlocks; ++i)
VerticalBlue[i] = new PlayerBlocks(params);
...
for (int i=0; i<NumberOfBlocks; ++i)
delete VerticalBlue[i];


You could use inheritance at this point, and instead write:
Object* VerticalBlue[NumberOfBlocks];

3. Use in-place construction. This is an advanced topic, so I discourage this.

-------

IMO, nr.2 should be your choice here.

Share this post


Link to post
Share on other sites
Quote:
Original post by deffer
Objects in an array can only be constructed via default constructor.
There's no C++ syntax allowing you to use other constructors, pass any parameters, etc.


Not 100% true.

object array[] = { object(1,2,3) , object(4,5,6) };

In this case, both elements of array are copy constructed from temporaries which in turn were constructed with (1,2,3) and (4,5,6) respectively.

psiko_scweek: It looks to me like the best solution here is a default constructor for Object, though.

Share this post


Link to post
Share on other sites
ok, the default constructors work fine and compile without errors.

I noticed though that the graphics or other objects in my game dont show...

if i use the default contructor i have to eliminate this line?!

Object(int tempx, int tempy, SDL_Surface *tempgraphic)

and instead use

Object()

hmmm....is there anything else i may have missed?

Share this post


Link to post
Share on other sites
unless you are a fan of hardcoding the objects in your game look into std::vector, and the other standard template libraries. std::vector is a dynamic array basically.

http://gpwiki.org/index.php/C_plus_plus:Modern_C_plus_plus:Vectors

one of my friends wrote that up. Should help you in understanding it.

to understand the basic idea here.

std::vector<object*> objectArray;
for(...){ create the objects
objectArray.push_back(new object(0,0,NULL));
}
you can access them with iterators or just like a regular array
objectArray[0]->setX(5);

just remember to delete objects on the heap if you need to :)
while(!objectArray.empty()){
delete objectArray[objectArray.size()-1];
objectArray.pop_back();
}
something along the lines of that...
When you get into polymorphism you will be really excited.

Share this post


Link to post
Share on other sites
Quote:
Original post by psiko_scweek
if i use the default contructor i have to eliminate this line?!


No, you can have multiple constructors.

Quote:
You can avoid the need for a default constructor, as std::vector does, by using placement new.


E.g. "in place construction" as deffer already mentioned and provided rationale against - although I'd argue it more along the point of "...why? It seems obvious we're constructing to a default - 'uninitialized' state - why not just use the default constructor, since that's what it's for?"

Share this post


Link to post
Share on other sites
Quote:
Original post by MaulingMonkey
Quote:
You can avoid the need for a default constructor, as std::vector does, by using placement new.


E.g. "in place construction" as deffer already mentioned and provided rationale against - although I'd argue it more along the point of "...why? It seems obvious we're constructing to a default - 'uninitialized' state - why not just use the default constructor, since that's what it's for?"


From my point of view, an object should never be in an "unitialized state" after construction. That's not the purpose of the constructor, its purpose is to construct the object, and bring it to an initialized state. Adding a default constructor "just for things to work", isn't reasonable.

In place construction seems very reasonable to me, the object doesn't exist before it's constructed, its just raw memory we're handling with, and once construction has taken place, the object is initialized and ready to be worked with.

Besides, it shouldn't be an "advanced topic" if you use an implementation such as std::vector.

Share this post


Link to post
Share on other sites
Quote:
Original post by GPX
Besides, it shouldn't be an "advanced topic" if you use an implementation such as std::vector.


If I get you right, you're saying that "if std::vector is using it, anybody can use it".
IMO, implementing (and doing it right) something as complex as std::vector is an advanced topic.

Share this post


Link to post
Share on other sites
Quote:
Original post by GPX
From my point of view, an object should never be in an "unitialized state" after construction. That's not the purpose of the constructor, its purpose is to construct the object, and bring it to an initialized state. Adding a default constructor "just for things to work", isn't reasonable.


"Uninitialized" is probably a misnomer here. A constructor should place an object in a known, consistent state which will not cause your destructor to explode, but it doesn't mean the object has to be immediately useful. The default constructor for a texture object may leave the texture "empty", requiring you to later call an initialization function to load an actual texture.

Not being able to fully initialize an object within the constructor is a commmon enough occurence. Sometimes you don't have a choice but to require a call to a post-construction initialization function.

Here, having a default constructor that creates an object using an ugly "default sprite" can be very useful.

Quote:
Original post by deffer
If I get you right, you're saying that "if std::vector is using it, anybody can use it".


This is not how I read what he said. I believe he meant that since std::vector does the in-place initialization for you, there is no need to worry about whether placement new is an advanced topic or not.

Share this post


Link to post
Share on other sites
Quote:
Original post by deffer
Quote:
Original post by GPX
Besides, it shouldn't be an "advanced topic" if you use an implementation such as std::vector.


If I get you right, you're saying that "if std::vector is using it, anybody can use it".
IMO, implementing (and doing it right) something as complex as std::vector is an advanced topic.


No, I meant using std::vector and not worrying about the implementation :-)
Although it is not complex at all, it's just a feature many people are not aware of, since it's not -that- useful. All it takes is using the syntax: MyClass* myObject = new(memoryPtr) MyClass(1,2,3), and later explicitly destructing the object using myObject->~MyClass().

Share this post


Link to post
Share on other sites
Quote:
Original post by GPX
No, I meant using std::vector and not worrying about the implementation :-)


Then I'm sorry. [smile]

Quote:

Although it is not complex at all, it's just a feature many people are not aware of, since it's not -that- useful. All it takes is using the syntax: MyClass* myObject = new(memoryPtr) MyClass(1,2,3), and later explicitly destructing the object using myObject->~MyClass().


The destructor part is what I'm woried about. In case of non-automatic destruction things can get messy (exception catching and rethrowing, that stuff). Using in-place new you're essentially duplicating std::vector's code.
Damn, if only std::vector had parameter passing for its in-place construction - we're stuck with its via-copy push_back :(

Share this post


Link to post
Share on other sites
Quote:
Original post by Fruny
"Uninitialized" is probably a misnomer here. A constructor should place an object in a known, consistent state which will not cause your destructor to explode, but it doesn't mean the object has to be immediately useful. The default constructor for a texture object may leave the texture "empty", requiring you to later call an initialization function to load an actual texture.

Not being able to fully initialize an object within the constructor is a commmon enough occurence. Sometimes you don't have a choice but to require a call to a post-construction initialization function.

Here, having a default constructor that creates an object using an ugly "default sprite" can be very useful.


I agree you sometimes have to compromise design-wise (we both agree "full construction" is cleaner), guess I'm just more fanatic.

Quote:
Original post by Fruny
This is not how I read what he said. I believe he meant that since std::vector does the in-place initialization for you, there is no need to worry about whether placement new is an advanced topic or not.


Yup, that's it :)

Share this post


Link to post
Share on other sites
Quote:

The destructor part is what I'm woried about. In case of non-automatic destruction things can get messy (exception catching and rethrowing, that stuff). Using in-place new you're essentially duplicating std::vector's code.
Damn, if only std::vector had parameter passing for its in-place construction - we're stuck with its via-copy push_back :(


But the whole point is being able to determine the values for the construction only later on, otherwise we could simply use a default constructor. Or perhaps now I am the one not understanding you :)

Share this post


Link to post
Share on other sites
Quote:
Original post by GPX
Quote:

The destructor part is what I'm woried about. In case of non-automatic destruction things can get messy (exception catching and rethrowing, that stuff). Using in-place new you're essentially duplicating std::vector's code.
Damn, if only std::vector had parameter passing for its in-place construction - we're stuck with its via-copy push_back :(


But the whole point is being able to determine the values for the construction only later on, otherwise we could simply use a default constructor. Or perhaps now I am the one not understanding you :)


I guess so, 'cause I don't understand what your comment has to do with what you quoted, lol [grin]

What I meant, is that the in-place contruction part is quite straightforward. The destruction code, on the other hand, is harder. You have to exactly know where to put it. In addition, you'd have to compensate for any possible exceptions being thrown. And, in case of OP's array of objects, keeping track of how many objects are initialized thus far.

In the end, the exact code for that is in std::vector's code, which is why I said "you're essentially duplicating std::vector's code" - without parametrised construction (unfortunately, that's the limitation of the language itself).

Share this post


Link to post
Share on other sites
Ok that STD::Vector stuff sounds like it would work exactly like I need it to,

but im having a problem getting it set up properly in my game...

any tips or information?

thanks again, you all have been extremely helpful!!

Share this post


Link to post
Share on other sites
Quote:
Original post by psiko_scweek
Ok that STD::Vector stuff sounds like it would work exactly like I need it to,


It's std::vector. C++ is case-sensitive.

Quote:
but im having a problem getting it set up properly in my game...

any tips or information?


Not if you don't explain what the "problem" you're having is. We cannot read your mind, you know.

Share this post


Link to post
Share on other sites
hehehe,

sorry you guys are just so great! :-)

anyways, here is the added code:

[SOURCE]
std::vector<PlayerBlocks> VerticalBlue;
for(int i = 0, i < NumberOfBlocks, ++i)
{
VerticalBlue.push_back(new PlayerBlocks(0,0,NULL));
}
[/SOURCE]


and the error im getting now is...

expected unqualified-id before 'for'

so, yeah im thinking i messed up somewhere... lol

Share this post


Link to post
Share on other sites
Quote:
Original post by Fruny
Quote:
Original post by GPX
From my point of view, an object should never be in an "unitialized state" after construction. That's not the purpose of the constructor, its purpose is to construct the object, and bring it to an initialized state. Adding a default constructor "just for things to work", isn't reasonable.


"Uninitialized" is probably a misnomer here.


Hence my careful quoting :). I'm taking uninitialized here to mean "not initialized to a 'useful' state" rather than "... to a known/consistant/not undefined by the C++ standard/placeholder state". The quoting comes from this being a different definition for this bit of terminology than the C++ standard uses throughout it's specification.

And no, using std::vector (at least in it's basic capacities) isn't an advanced topic. But then you're using std::vector, not placement new.

Quote:
Original post by psiko_scweek
anyways, here is the added code:

*** Source Snippet Removed ***


Problem #1: You try to push_back a pointer into a container of values ("hint": get rid of the new)

Problem #2:
Right: for ( initialization ; conditional ; iteration )
Wrong: for ( initialization , conditional , iteration )
Problem #3?: Based on your error, you may have frogoten to #include <vector>, whatever defines PlayerBlocks, whatever defines NumberOfBlocks, or made a typeo with respect to any of these.

Share this post


Link to post
Share on other sites
Quote:
Original post by psiko_scweek
hehehe,

sorry you guys are just so great! :-)

anyways, here is the added code:

*** Source Snippet Removed ***[/source]

and the error im getting now is...

expected unqualified-id before 'for'

so, yeah im thinking i messed up somewhere... lol


You want semicolons, not commas, in your for loop, although I don't see why that would cause that error:

for(int i = 0;i < NumberOfBlocks;++i)

Is PlayerBlocks definately defined at that point? Have you included <vector>?

Share this post


Link to post
Share on other sites
ok, i tried what you all suggested, and im sorry if im getting annoying. Here is the newest.


1) vector is included at the very beginning.
2) PlayerBlocks is defined before that point.
3) NumberOfBlocks is an int with the value of 8

and here is my newest batch of errors...


im still getting the
"expected unqualified-id before for"

and now im getting
"expected constructor, destructor, or type conversion before < token"
and
"expected constructor, destructor, or type conversion before ++ token"

here is my new code

[SOURCE]

/////////// CREATE THE OBJECTS ///////////
//PlayerBlocks VerticalBlue[NumberOfBlocks];

std::vector<PlayerBlocks> VerticalBlue;
for(int i = 0;i < NumberOfBlocks;i++)
{
VerticalBlue.push_back(PlayerBlocks(0,0,NULL));
}

[/SOURCE]


im lost and confused...


Share this post


Link to post
Share on other sites
ok wow im an idiot, i had the for loop outside of the main loop and not in a function so it was not working of course.

got that fixed, but it still isnt working :-( now my game doesnt do anything. oh well ill work on that later.

Share this post


Link to post
Share on other sites

This topic is 4106 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this