Welcome, Guest. Please login or register.
Did you miss your activation email?

Login with username, password and session length

 
Advanced search

879978 Posts in 33014 Topics- by 24385 Members - Latest Member: jhewitt

May 25, 2013, 12:09:35 PM
TIGSource ForumsDeveloperTutorialsA game from scratch in C++ using SFML
Pages: 1 [2] 3 4
Print
Author Topic: A game from scratch in C++ using SFML  (Read 18000 times)
Average Software
Level 10
*****

Fleeing all W'rkncacnter


View Profile WWW Email
« Reply #15 on: September 14, 2011, 08:00:37 AM »

Right, so does this go for objects of trivial construction cost only, or for all objects with move ctors?

It applies to any object.  It's usually an advantage for the optimizer to know exactly what kind of object it's working with.  Pass by reference doesn't get you that, at least not in C++, since the object could be of some derived type (Ada, for example, allows you to pass strict types by reference.  That is, you can have a function that accepts a reference to a Doodad, and only a Doodad.  No types derived from Doodad are allowed.  I'd like to see this feature in more languages).

Of course, it's very situational.  You really have to analyze performance and see what works best.  Even after move construction becomes common, there will probably still be cases where pass by reference gets you better performance, there will just be fewer of them.

I guess the point is that there is no magic passing method that guarantees better performance, it's entirely situational.  You have to take the properties of the object, and what the function is actually doing into account as well.  There's no substitute for performance testing.
Logged

Franchise - The restaurant wars begin!

What would John Carmack do?
Serapth
Level 2
**


View Profile
« Reply #16 on: September 14, 2011, 08:47:57 AM »

Thank you two for the feedback, I have made some updates accordingly.  I agree with what you said Mikademus regarding the Bjarne comment, it has been removed. 

Excellent point regarding constness, I really need to pay more attention and priority to doing that correctly. 

I do have a question and the answer may simply be "it's just the way things are done", but what is with the C++ trend of putting const at the end of the statement, instead of at the beginning like commonly seen in C# or Java ( or frankly, in C back in the day )?
Logged
Average Software
Level 10
*****

Fleeing all W'rkncacnter


View Profile WWW Email
« Reply #17 on: September 14, 2011, 10:13:56 AM »

I do have a question and the answer may simply be "it's just the way things are done", but what is with the C++ trend of putting const at the end of the statement, instead of at the beginning like commonly seen in C# or Java ( or frankly, in C back in the day )?

Are you referring to things like this:

Code:
class Something
{
public:
    void some_method();
    void some_other_method() const; // <--- here
};

I think you might be confusing concepts.  C++ allows constant instances of objects, C# and Java do not (to the best of my knowledge).  Tagging member functions with 'const' means that the operation is allowed to be used by a constant object. (Or an object referred to by a pointer or reference to const, which might actually be constant)

That is, C++ lets you do this:

Code:
const Something my_thing; // <--- This object is constant.

my_thing.some_other_method(); // OK!  This is a const method.
my_thing.some_method(); // ERROR!  This method can change the object, so it can't be used on a constant one.

This idea is very important in allowing the compiler to catch mistakes, since const methods are not allowed to alter their objects (forget about mutable for now).

If you have an object that draws itself, for example, you probably don't want the object to change during the draw function.  By tagging it as const, the compiler will ensure that this is the case, and if you accidentally try to change the object while drawing, it will be an error.
Logged

Franchise - The restaurant wars begin!

What would John Carmack do?
Serapth
Level 2
**


View Profile
« Reply #18 on: September 14, 2011, 10:33:08 AM »

You are correct, and I am confusing concepts.

So when you tag a member function as const you are essentially creating a contract(exception) with the compiler that const instances of this class can safely call this function as you are promising not to make any Changes?


Off topic: wow there is something with the site, perhaps the million emoticons but that post just too me about 10 my transformer tablet. I've experienced lag before, but but nothing like this.
Logged
Average Software
Level 10
*****

Fleeing all W'rkncacnter


View Profile WWW Email
« Reply #19 on: September 14, 2011, 10:45:26 AM »

So when you tag a member function as const you are essentially creating a contract(exception) with the compiler that const instances of this class can safely call this function as you are promising not to make any Changes?

Yes, that's exactly it.

It's a very important thing to get right, especially as programs get larger.  For example, when I do C++ games I generally have a class like this:

Code:
class Drawable
{
public:
    virtual void draw() const = 0;
};

Everything that can be drawn inherits this, and by making it const I ensure that a draw operation will never alter an object.  If I screw this up anywhere and try to change something the compiler says, "hey, you said you wouldn't do that!" and I can fix the problem.
Logged

Franchise - The restaurant wars begin!

What would John Carmack do?
megamjau
Level 0
*


View Profile
« Reply #20 on: September 14, 2011, 01:17:25 PM »

Just finished going through part 5.. There seems to be a mixup with the GameObjectManager.cpp source code box as it is showing the VisibleGameObject.cpp source code. But the link to the GameObjectManager.cpp works.

I also get an error from the Remove function in the GameObjectManager when I try to compile.

GameObjectManager.cpp: In member function 'void GameObjectManager::Remove(std::string)':
GameObjectManager.cpp:24: error: no matching function for call to 'std::map<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, VisibleGameObject*, std::less<std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<const std::basic_string<char, std::char_traits<char>, std::allocator<char> >, VisibleGameObject*> > >::erase(std::_Rb_tree_const_iterator<std::pair<const std::basic_string<char, std::char_traits<char>, std::allocator<char> >, VisibleGameObject*> >&)'
/usr/include/c++/4.2.1/bits/stl_map.h:453: note: candidates are: void std::map<_Key, _Tp, _Compare, _Alloc>::erase(typename std::_Rb_tree<_Key, std::pair<const _Key, _Tp>, std::_Select1st<std::pair<const _Key, _Tp> >, _Compare, typename _Alloc::rebind<std::pair<const _Key, _Tp> >::other>::iterator) [with _Key = std::basic_string<char, std::char_traits<char>, std::allocator<char> >, _Tp = VisibleGameObject*, _Compare = std::less<std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, _Alloc = std::allocator<std::pair<const std::basic_string<char, std::char_traits<char>, std::allocator<char> >, VisibleGameObject*> >]
/usr/include/c++/4.2.1/bits/stl_map.h:468: note:                 typename std::_Rb_tree<_Key, std::pair<const _Key, _Tp>, std::_Select1st<std::pair<const _Key, _Tp> >, _Compare, typename _Alloc::rebind<std::pair<const _Key, _Tp> >::other>::size_type std::map<_Key, _Tp, _Compare, _Alloc>::erase(const _Key&) [with _Key = std::basic_string<char, std::char_traits<char>, std::allocator<char> >, _Tp = VisibleGameObject*, _Compare = std::less<std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, _Alloc = std::allocator<std::pair<const std::basic_string<char, std::char_traits<char>, std::allocator<char> >, VisibleGameObject*> >]
/usr/include/c++/4.2.1/bits/stl_map.h:483: note:                 void std::map<_Key, _Tp, _Compare, _Alloc>::erase(typename std::_Rb_tree<_Key, std::pair<const _Key, _Tp>, std::_Select1st<std::pair<const _Key, _Tp> >, _Compare, typename _Alloc::rebind<std::pair<const _Key, _Tp> >::other>::iterator, typename std::_Rb_tree<_Key, std::pair<const _Key, _Tp>, std::_Select1st<std::pair<const _Key, _Tp> >, _Compare, typename _Alloc::rebind<std::pair<const _Key, _Tp> >::other>::iterator) [with _Key = std::basic_string<char, std::char_traits<char>, std::allocator<char> >, _Tp = VisibleGameObject*, _Compare = std::less<std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, _Alloc = std::allocator<std::pair<const std::basic_string<char, std::char_traits<char>, std::allocator<char> >, VisibleGameObject*> >]


It might just be a missing import or a different implementation of map or something, since I'm not using visual studio and "StdAfx".
Logged
Serapth
Level 2
**


View Profile
« Reply #21 on: September 14, 2011, 01:56:55 PM »

Oops...  downside to last minute edits.  The right code is now there, thanks for the heads up.

What platform/compiler are you using?  It doesn't appear to be an include issue though ( although you did point out I forgot to add <map> to stdafx... oops again ), it found std::map just fine, it seems to be indicating that std::map does not have an erase() method that takes a single parameter.  That said, stl error messages have never been fun to parse.


Could you try one thing for me?  Change Remove from:

void GameObjectManager::Remove(std::string name)
{
   std::map<std::string, VisibleGameObject*>::const_iterator results = _gameObjects.find(name);
   if(results != _gameObjects.end() )
   {
      delete results->second;
      _gameObjects.erase(results);
   }
}

to

void GameObjectManager::Remove(std::string name)
{
   std::map<std::string, VisibleGameObject*>::iterator results = _gameObjects.find(name);
   if(results != _gameObjects.end() )
   {
      delete results->second;
      _gameObjects.erase(results);
   }
}


and tell me if that resolves your problem?
« Last Edit: September 14, 2011, 02:17:42 PM by Serapth » Logged
megamjau
Level 0
*


View Profile
« Reply #22 on: September 14, 2011, 02:23:47 PM »

Changed const_iterator to iterator as per your suggestion and it works like a charm. Smiley

I'm using gcc on mac os x.
Logged
Serapth
Level 2
**


View Profile
« Reply #23 on: September 14, 2011, 02:27:38 PM »

Alright, that makes complete sense actually and was an error on my part.  It should have been an iterator ( not a const_iterator ) all along, cut and paste coding bit me in the butt on this one.

What I am extremely confused about is why Visual Studio happily compiled and allowed me to pass a const_iterator to std::map.erase() in the first place?  I would think that would not work on any platform.

I am guessing I should code along in parallel on my Mac to catch these kinds of things.  Anyways, I have updated the source files to use a more cross platform friendly iterator. Smiley  Also snuck in a stealth edit to actually include <map> this time...   Who, Me?
« Last Edit: September 14, 2011, 02:35:45 PM by Serapth » Logged
Average Software
Level 10
*****

Fleeing all W'rkncacnter


View Profile WWW Email
« Reply #24 on: September 14, 2011, 02:40:03 PM »

What I am extremely confused about is why Visual Studio happily compiled and allowed me to pass a const_iterator to std::map.erase() in the first place?  I would think that would not work on any platform.

In my experience Visual C++ lets you get away with a lot of things you aren't supposed to be able to do.  GCC is a much more strict compiler.

Having ported relatively large VC++ projects to other platforms, this is a major pain in the ass.
Logged

Franchise - The restaurant wars begin!

What would John Carmack do?
Mikademus
Level 10
*****


The Magical Owl


View Profile
« Reply #25 on: September 15, 2011, 01:02:58 AM »

That is certainly true. Some but not all problems can be avoided by going to the project settings and turn off "Microsoft Language Extensions", which defaults to on, iirc.
Logged

\\\"There\\\'s a tendency among the press to attribute the creation of a game to a single person,\\\" says Warren Spector, creator of Thief and Deus Ex. --IGN<br />My compilation of game engines for indies
Serapth
Level 2
**


View Profile
« Reply #26 on: September 15, 2011, 09:51:20 AM »

So, if I just finished recompiling and getting everything to work with XCode, and the fight was more with getting XCode working but there were a couple code changes required. First off, gcc does not allow you to specify a nested enums type, which I view as a shame as it is less readable. It also failed on _tchar which is included just for Microsofts _tmain.

Starting with Pang5 I will make sure all releases work on Mac and Windows, even though the tutorial is specifically about Visual C+ +, Express. Simply put writing non portable code would just be silly.

Oh and this is my first experience with XCode 4.2 but frankly it seems... horrible. Nothing is intuitive, it's slow, but debugging is cumbersome and every time I google anything it seems to be aa rant about how broken things are since 3.x. Being new to XCode I am in no position to judge but it seems like a dud.
Logged
Average Software
Level 10
*****

Fleeing all W'rkncacnter


View Profile WWW Email
« Reply #27 on: September 15, 2011, 10:12:30 AM »

First off, gcc does not allow you to specify a nested enums type, which I view as a shame as it is less readable.

I do nested enums in GCC all the time.  Post the code, you must be doing something wrong.
Logged

Franchise - The restaurant wars begin!

What would John Carmack do?
Serapth
Level 2
**


View Profile
« Reply #28 on: September 15, 2011, 10:28:13 AM »

First off, gcc does not allow you to specify a nested enums type, which I view as a shame as it is less readable.

I do nested enums in GCC all the time.  Post the code, you must be doing something wrong.

No, I you misunderstand. My punctuation wasn't clear, it should have read "specify a nested enum's type".

For example:

class example
{
public:
enum Colours { Red, Blue} ;
} ;


Colours red = example::Colours::Red

« Last Edit: September 15, 2011, 11:54:15 AM by Serapth » Logged
Average Software
Level 10
*****

Fleeing all W'rkncacnter


View Profile WWW Email
« Reply #29 on: September 15, 2011, 10:36:47 AM »

First off, gcc does not allow you to specify a nested enums type, which I view as a shame as it is less readable.

I do nested enums in GCC all the time.  Post the code, you must be doing something wrong.

No, I you misunderstand. My punctuation wasn't clear, it should have read "specify a nested enums type".

For example:

class example
{
public:
enum Colours { Red, Blue} ;
} ;


Colours red = example::Colours::Red



That's actually a new feature in C++2011.  GCC has it in version 4,4 and higher, but I don't think Apple ever went past GCC 4.2.  The MS compiler must have already implemented it and enabled it by default.  In C++98, that is indeed illegal.
Logged

Franchise - The restaurant wars begin!

What would John Carmack do?
Pages: 1 [2] 3 4
Print
Jump to:  

Theme orange-lt created by panic