C++ style Programming

If you are a new Irrlicht Engine user, and have a newbie-question, this is the forum for you. You may also post general programming questions here.
Post Reply
torleif
Posts: 188
Joined: Mon Jun 30, 2008 4:53 am

C++ style Programming

Post by torleif »

I have a few basic C++ style questions.

Lets say I have a class:

Code: Select all

class Foo {
  public:
    static foobar(){};     // I use this
    static const Foo(){}; // Other programmers seem to use this
}
I understand what static does, I use it to make functions that access the class but not the object. I only use const for function(input) to ensure it won't change. But why do other programmers use static const?


Irrlicht has typedefs for certain size bytes, for example c8 for 8 bit char, u32 for a 32 bit integer. I understand this for portability, but what one of these is the best to do:

myFile->read(&inChar, sizeof( c8 )); // this
myFile->read(&inChar, 1); // or this
hybrid
Admin
Posts: 14143
Joined: Wed Apr 19, 2006 9:20 pm
Location: Oldenburg(Oldb), Germany
Contact:

Post by hybrid »

Are you sure that they use static const for functions without defining the return value type? After all, the const is for the return value, so it would only make sense for some reference return values. Making a static method const is not allowed, but also not useful, because it's const by default (it cannot alter an object - it's static). Other uses of const are for const member attributes, which are stored in the class instead of in each object.
Oh, and moved to beginner's section, because it's a C++ question :wink:
torleif
Posts: 188
Joined: Mon Jun 30, 2008 4:53 am

Post by torleif »

Yes, I should have mentioned that there are return values
christianclavet
Posts: 1638
Joined: Mon Apr 30, 2007 3:24 am
Location: Montreal, CANADA
Contact:

Post by christianclavet »

Oh Boy! I have a long way to get there! :?
Is there any good sites for beginners that you'd recommend about this that would like to improve their coding style?
JP
Posts: 4526
Joined: Tue Sep 13, 2005 2:56 pm
Location: UK
Contact:

Post by JP »

It's generally best to use sizeof(c8), or whatever, when you're specifying the size of something because on different platforms they can be different sizes sometimes, there's no guarantee. So a c8 is a char and a char is 1 byte on windows and it's probably 1 byte everywhere else too but imagine there's a super cool platform called LOLLARSK80RZ!!1 and this platform actually sues 2 bytes to store a char. If you port your code and have used something like myFile->read(&inChar, 1); then it's not going to be very happy about it. sizeof(c8) would automatically stick in the correct byte size for the LOLLARSK80RZ!!1 platform and you'd be problem free.
Image Image Image
hybrid
Admin
Posts: 14143
Joined: Wed Apr 19, 2006 9:20 pm
Location: Oldenburg(Oldb), Germany
Contact:

Post by hybrid »

The problem is that the file only provides a 1 byte char, hence reading two byte chars would result in core dumps. It's best to stick to fixed numbers when reading binary files, and to use the official types when writing (so don't use f32 when writing a float, because f32 could as well be a fixed point math class). However, all binary file handling can (and usually will) break at some point.
rogerborg
Admin
Posts: 3590
Joined: Mon Oct 09, 2006 9:36 am
Location: Scotland - gonnae no slag aff mah Engleesh
Contact:

Re: C++ style Programming

Post by rogerborg »

torleif wrote: Lets say I have a class:

Code: Select all

class Foo {
  public:
    static foobar(){};     // I use this
    static const Foo(){}; // Other programmers seem to use this
}
This is not valid C++, so I guess we'd be wasting our time discussing it.

torleif wrote: Irrlicht has typedefs for certain size bytes, for example c8 for 8 bit char, u32 for a 32 bit integer. I understand this for portability, but what one of these is the best to do:

Code: Select all

myFile->read(&inChar, sizeof( c8 )); // this
myFile->read(&inChar, 1); // or this
In principle, if inChar is a value type, then using its size would be safest, since if you change the type of inChar then you don't have to change the sizeof():

Code: Select all

myFile->read(&inChar, sizeof(inChar));

However, in practice, if inChar is of type c8, then sizeof(c8) is fine. If c8 isn't 1 byte, then that's an error in the definition of c8.

And in this specific case, of reading binary data, you want to read an exact size, defined by the file format; if you accidentally read 2 bytes when the value that you want is in 1 byte, then you've screwed up your reader.

So for the purposes of reading formatted binary data, I would actually use:

Code: Select all

myFile->read(&inChar, 1);
Last edited by rogerborg on Fri Jul 25, 2008 8:11 am, edited 1 time in total.
Please upload candidate patches to the tracker.
Need help now? IRC to #irrlicht on irc.freenode.net
How To Ask Questions The Smart Way
JP
Posts: 4526
Joined: Tue Sep 13, 2005 2:56 pm
Location: UK
Contact:

Post by JP »

hybrid wrote:The problem is that the file only provides a 1 byte char, hence reading two byte chars would result in core dumps. It's best to stick to fixed numbers when reading binary files, and to use the official types when writing
Yeah i had considered that if you were reading a file you wouldn't want to read 2 if it had been written as 1 but i was keeping it simple i guess :lol:
Image Image Image
torleif
Posts: 188
Joined: Mon Jun 30, 2008 4:53 am

Post by torleif »

Thanks for your responses, in the future I will use

Code: Select all

myFile->read(&inChar, 1); // or this
For all my binary input. I guess you should too :P

Sorry about by mistype with my class structure, it really should have been:

Code: Select all

class Foo {
  public:
    static genStruct foobar(){};     // I use this
    static const genStruct Foo(){}; // Other programmers seem to use this
} 
Where genStruct is some structure, object or primitive. (I guess that's where it makes a difference?)

Perhaps the difference static const and const are simply performance issues I shouldn't be concerned with
rogerborg
Admin
Posts: 3590
Joined: Mon Oct 09, 2006 9:36 am
Location: Scotland - gonnae no slag aff mah Engleesh
Contact:

Post by rogerborg »

torleif wrote:

Code: Select all

    static const genStruct Foo(){}; // Other programmers seem to use this
I'll assume that you mean some method other than Foo(), since constructors can't have qualifiers or return types.

Whether this is useful depends on whether genStruct is a value or a reference type. If it's a value type, (e.g. int, or a class/structure returned by value rather than by reference) then there's no point in returning a const version, since it's just dumped on the stack and the caller will be taking a copy of it anyway, and you can't effect their version of it.

However, if you're returning a reference type, i.e. a pointer (e.g. int *) or a reference (e.g. genStruct &) then const is useful, as it stops(1) the caller from modifying the thing that you are returning a reference so.

(1) Except it doesn't really...

Code: Select all

class GotSome
{
public:
    // These methods are static, which means that you don't need an instance
    // of GotSome to call them on.  You can just call GotSome::getSome()
    // and get returned a pointer to some.
    // Note that the pointer/reference are not constant, but the thing that 
    // they point/refer to is const.
    // This means that the caller can't - or rather, that it shouldn't - 
    // change the value of "some" using these methods, they can only get it.
    // Because these are static methods, the methods themselves can't be
    // declared const.  This would be meaningless, since they don't have
    // an object to be called on.
    static const int * getSome(void) { return &some; }
    static const int & getSomeMore(void) { return some; }
    
    // These are instance versions of the above methods.  That means that
    // they are not declared static, so they require an instance of GotSome.
    // You can't call GotSome::getSomeInstance().  Instead, you need to do (e.g.):
    // GotSome aSome;
    // const int * something = aSome.getSomeInstance().
    //
    // The methods themselves are declared const.  This tells that compiler that
    // calling them won't result in the object being altered; or at least
    // not within the method body.
    const int * getSomeInstance(void) const { return &some; }
    const int & getSomeMoreInstance(void) const { return some; }

private:
    static int some;
};

// define the static member, and set its initial value.
// Now, because all the methods that access this return a reference to const,
// it shouldn't be possible for this to change.
int GotSome::some = 1066;

int main()
{
    // All as it should be
    const int * theInt = GotSome::getSome();
    (void)printf("%d\n", *theInt);
    // *theInt = 1314; // The compiler won't let us do this, as theInt points to a const int.

    // Unfortunately, const is more a guidelines than a rule, and the caller can
    // just brutally cast it away.
    GotSome aSome;
    int & theConstIsALie = const_cast<int &>(aSome.getSomeMoreInstance());
    theConstIsALie = 1314;

    // Let's just be absolutely sure that this has changed the class member
    int * liesDamnLies = const_cast<int *>(aSome.getSomeInstance());
    (void)printf("%d\n", *liesDamnLies);

    // Thus ends the lesson on the uses and limitations of const.
    return 0;
}
Please upload candidate patches to the tracker.
Need help now? IRC to #irrlicht on irc.freenode.net
How To Ask Questions The Smart Way
Post Reply