Jump to content
  • Advertisement
Sign in to follow this  
Dark Sage

C++ Question About Objects

This topic is 1029 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

When creating an object in C++ I would like to create the object and call a function inside that object at the same time. For instance, say I have a "Level" class and inside that class there is a function that loads the level called "load(string level)".

 

Instead of doing this:

Level level;
level.load("level1");

Is there any way to do something like this:

Level level = new Level("level1").load; // I believe this is possible in Java, however it has been quite a while since I programmed in Java.

And I know that the "new" keyword functions a lot different in C++ than it does in Java, so I have been reluctant to try anything that included using it. It is not that big of an issue I just think it looks nicer when it's all on one line.

Edited by Dark Sage

Share this post


Link to post
Share on other sites
Advertisement

If all you are actually concerned about is the syntax and the separate call to load, then just do the loading in the constructor instead of in a separate load function.

Level level("level1");

Share this post


Link to post
Share on other sites

That makes sense. Guess it's just because I haven't learned about destructors yet, and I would assume that if I am doing the level loading in the constructor I would have to destruct the old level before loading another one. I could just be over complicating it though...

Share this post


Link to post
Share on other sites

Hello, you're mixing up a couple of things.

Firstly, you want to do stuff on the same line. This is easier than you think:

Level level; level.Load("level1");

Tadaa! However, in general, it is more readable to use shorter lines, especially since debuggers usually work on a per line basis. So, stepping through the line above will likely be quite awkward.

 

Secondly, you're talking about new, constructors and destructors.

Let me try to untangle this a bit.

 

Whether you use "new" or not, an objects constructor and destructor will still be run (if it has any). So they don't have anything to do with the use of "new".

 

Instead, "new" will change where the object will life and therefore influence it's lifetime.

In short, without "new", the object will live until the current scope ends (at the next "}"). With "new", the object will live until "delete" is called on it.

For a more detailed explanation, this looks to be fairly comprehensive:

http://www.programmerinterview.com/index.php/data-structures/difference-between-stack-and-heap/

 

For the sake of completeness, here's how the above example would work with "new", again as a single line.:

Level* level = new Level(); level->load("level1");

I hope that helps!

Share this post


Link to post
Share on other sites

Oh, another thing: In Java, objects are *always* on the heap, so you don't have a choice to make there. Only primitives (int, float,...) are on the stack.

Share this post


Link to post
Share on other sites

Hello, you're mixing up a couple of things.

Firstly, you want to do stuff on the same line. This is easier than you think:

Level level; level.Load("level1");

Tadaa! However, in general, it is more readable to use shorter lines, especially since debuggers usually work on a per line basis. So, stepping through the line above will likely be quite awkward.

 

Secondly, you're talking about new, constructors and destructors.

Let me try to untangle this a bit.

 

Whether you use "new" or not, an objects constructor and destructor will still be run (if it has any). So they don't have anything to do with the use of "new".

 

Instead, "new" will change where the object will life and therefore influence it's lifetime.

In short, without "new", the object will live until the current scope ends (at the next "}"). With "new", the object will live until "delete" is called on it.

For a more detailed explanation, this looks to be fairly comprehensive:

http://www.programmerinterview.com/index.php/data-structures/difference-between-stack-and-heap/

 

For the sake of completeness, here's how the above example would work with "new", again as a single line.:

Level* level = new Level(); level->load("level1");

I hope that helps!

Thanks for your help and information. Clears up a few things I was definitely confused about haha.

Share this post


Link to post
Share on other sites

A final note FYI.

Do not call overriden functions (pure virtual) from base class ctor. So you cannot do something like:

class Asset {
public:
  Asset(const std::string &foo) { Load(foo); }
protected:
  virtual void Load(const std::string &foo) = 0;
};

class Level : public Asset {
public:
  Level (const std::string &foo) : Asset(foo) { }
protected:
  void Load(const std::string &foo) {
    // Pull physics
    // Pull textures
    // Pull sound resources
  }
};

To build a Level object the runtime first builds the Asset object. When the Asset object ctor is run, it has no information about what's really running and you'll be screwed big way. I think some compilers warn you or even prevent you from doing that. I am 100% sure I have been screwed in the past.

If memory serves, Java allows this for some reasons I don't remember. I'd suggest to be careful with that.

 

EDIT: see Brother Bob for a more "technically correct" explanation. I still suggest to stay away from those things but that's opinion at this point.

Edited by Krohm

Share this post


Link to post
Share on other sites

Level (const std::string &foo) : Asset(foo) { }

 

Careful with that.

 

How long does loading a level take?  A half second?  Five seconds? Ten seconds? Two minutes?

 

Temporary objects get created all the time.  Sometimes you want to create empty objects, such as when you allocate an array of things.

 

It is generally best to provide a default constructor that does nothing except create an empty object, and a copy constructor that generally works with shallow copies of members. In this case the default constructor would be an unloaded level. This should only initialize the values needed to specify the level is unloaded, and return immediately.

 

You can still write constructors with parameters like that, internally they call the load function and wait for the seconds or minutes required to do the job.  But make sure those are not the ONLY constructor you create.  Build an instantly constructable default as well.

Share this post


Link to post
Share on other sites

A final note FYI.

Do not call overriden functions (virtual) from base class ctor. So you cannot do something like:

class Asset {
public:
  Asset(const std::string &foo) { Load(foo); }
protected:
  virtual void Load(const std::string &foo) = 0;
};

class Level : public Asset {
public:
  Level (const std::string &foo) : Asset(foo) { }
protected:
  void Load(const std::string &foo) {
    // Pull physics
    // Pull textures
    // Pull sound resources
  }
};

To build a Level object the runtime first builds the Asset object. When the Asset object ctor is run, it has no information about what's really running and you'll be screwed big way. I think some compilers warn you or even prevent you from doing that. I am 100% sure I have been screwed in the past.

If memory serves, Java allows this for some reasons I don't remember. I'd suggest to be careful with that.

 

Java and C# allow this because the construction of a derived object runs in the opposite fashion from a C++ object. In Java/C# first the derived object is created with its associated vtable, this means that the constructor knows where to dispatch a virtual function call too. In C++ first the base object is created and then the derived version, calling a virtual function is in that case undefined behaviour for C++.

Share this post


Link to post
Share on other sites

 In C++ first the base object is created and then the derived version, calling a virtual function is in that case undefined behaviour for C++.

 

Calling virtual functions form the base class constructor is perfectly fine and well specified. During construction of the Asset base class, the concrete type of the object is Asset (the concrete type is not Level until later during construction) and the virtual call is dispatched to Asset::Load.

 

Since Asset::Load is pure there is a chance it also has no implementation. In that case I believe the behaviour of calling Load is undefined. Otherwise, there are no problems calling virtual functions other than ones understanding of the rules.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!