Page 1 of 2

c++ class inheritence

Posted: Wed Sep 19, 2007 5:59 am
by Zacariaz
The inheritance concept has confused me a bit although i think i more or less understand it now.

Code: Select all

typedef unsigned long long uint64;
class Piece {
  const bool Color:1;
  unsigned char Pos:6;
public:
  Piece(const bool b,const unsigned char x,unsigned const char y):Color(b),Pos(x + (y * 8)) {}
  uint64 getpos() const {return 1ull<<Pos;}
  bool move(const char x,const char y) {
    const char test = x + (y * 8) + Pos;
    if(test >= 0 && test < 64) {
      Pos = test;
      return 0;
    }
    else return 1;
  }
};
class King : public Piece {
public:
  King(const bool b,const unsigned char x,const unsigned char y) : Piece(b,x,y) {}
};
This is just some code, what it is for is not important, what i need to know is if i have got the inheritance part right.
1. class King should be and exact copy of class Piece as it contain nothing more than the constructor call. Is this correct?
2. I have tried different ways of writing class King's constructor, as it should be inherited automaticly (or so i thought) from the base class. This was seems to be the only thing that works. I have a hard time accepting that the constructor cant just be inherited.
3. Is there anyway to prevent other "users" of class Piece than class King?
4. other comments and stuff are welcome as usual, but im not interested in a long discusion, i just want to know if i got it right.

Thanks

Re: c++ class inheritence

Posted: Wed Sep 19, 2007 6:55 am
by Solar
Zacariaz wrote:1. class King should be and exact copy of class Piece as it contain nothing more than the constructor call. Is this correct?
Yes.

As an aside, any class from which you intend to inherit and which sports a constructor should contain a destructor declared as virtual, i.e. virtual ~Piece() {}. The explanation is a bit involved, just get into the habit for now.
2. I have tried different ways of writing class King's constructor, as it should be inherited automaticly (or so i thought) from the base class. This was seems to be the only thing that works. I have a hard time accepting that the constructor cant just be inherited.
Only the default constructor can "just be inherited" (if even that much, haven't tried it).

You told the compiler that Piece can only be constructed in the way you specified. Since every King object contains a Piece object, you have to tell the compiler in the King constructor how to construct that Piece object first.
3. Is there anyway to prevent other "users" of class Piece than class King?
You could keep the Piece header away from the public, but that isn't "secure" either, and for an "insecure" solution it should suffice to add a comment to the Piece header not to inherit from it.
4. other comments and stuff are welcome as usual, but im not interested in a long discusion, i just want to know if i got it right.
As nice as it is to see you have found an interesting project to test your C++ skills on, this is the umpteenth topic on this board about poker cards. Perhaps a single topic "Zacariaz' C++ Q&A" would be better.

And your examples could be a bit more... examplish. You know, class Base and class Child, no bitfields or program logic that has nothing to do with the subject. This is not due to a dislike towards poker, it just helps communication. It keeps people focussed on what you want to know, and usually helps you understanding the question better even before you post.

Oh, and your coding style is a bit hard to read. Most of the C++ code out there uses 4 space indents, spaces after ( and , as well as in front of ), and lists data members last in a class declaration. But that's only style, i.e. in the eyes of the beholder.

And while I'm nagging at banalities, another useful habit is to place the "const" always after the thing you're declaring const. In some places, you cannot put "const" first, and by putting it always last makes it more consistent.

Posted: Wed Sep 19, 2007 7:15 am
by JamesM
Oh, and your coding style is a bit hard to read. Most of the C++ code out there uses 4 space indents, spaces after ( and , as well as in front of ), and lists data members last in a class declaration. But that's only style, i.e. in the eyes of the beholder.
A lot of code uses 2-space indents. Both myself and my employer's coding standard does. I do tend to put spaces before (, e.g.

Code: Select all

int a = doFunc (3);
But I will only put spaces after ( and before ) when using nested paranthesis, and then at my own discretion (again, in line with my company's coding standard.

I agree with listing data members last. And I personally don't like having { on the same line - I put a line break in:

Code: Select all

void func ()
{
And, Solar, it looks to me more like he's designing a chess implementation, considering he's using a 8*8 board ;)

Zacariaz: if you are implementing a chess engine, I would point you towards BitBoards (check wikipedia) as a useful implementation method. I personally didn't use them, and although my implementation is fast (ish), it can only do 8-9 plys in 10 seconds. It's competitive against GNU chess, although the lack of an opening book is to it's detriment :(

Re: c++ class inheritence

Posted: Wed Sep 19, 2007 8:07 am
by Colonel Kernel
Solar wrote:And while I'm nagging at banalities, another useful habit is to place the "const" always after the thing you're declaring const. In some places, you cannot put "const" first, and by putting it always last makes it more consistent.
Really? I've never heard that before. In fact I was just discussing this at work the other week (wondering why some people were writing Foo const* instead of const Foo*). In what situation can you not put "const" first?

Posted: Wed Sep 19, 2007 8:52 am
by Solar
Foo const *, for example. Think about it. 8)

(Hint: What if you want the pointer to be constant, not the stuff it points to?)

Posted: Wed Sep 19, 2007 8:57 am
by JamesM
function definitions?

Code: Select all

void *func(int a) const
{
Will not compile with g++:
g++ wrote:test.cc:5: error: non-member function `int func(int)' cannot have `const'
method qualifier
Whereas this:

Code: Select all

const void *func(int a)
{
Will compile.

When used as a qualifier to member functions, both seem to compile. I'm not quite certain what is going on at the syntactic level here at all ... :S

JamesM

Posted: Wed Sep 19, 2007 9:37 am
by Tyler
JamesM wrote:function definitions?

Code: Select all

void *func(int a) const
{
Will not compile with g++:
g++ wrote:test.cc:5: error: non-member function `int func(int)' cannot have `const'
method qualifier
Whereas this:

Code: Select all

const void *func(int a)
{
Will compile.

When used as a qualifier to member functions, both seem to compile. I'm not quite certain what is going on at the syntactic level here at all ... :S

JamesM
The First Code Snippet is valid only as a Class Member, and declares that that function "promises" not to change any member Variables of the class. I believe you are trying to compile it as a Global Definition, making it invalid as the const makes the "this" pointer constant, and Global Variables have no such pointer.

Posted: Wed Sep 19, 2007 10:58 am
by Candy
What about const? (to the tune of Michael Jackson's What about us?)

For a simple function, there are so many places you could put const. Now, what do they mean?

void *&transmogrify(void *&arg) {...}

I can think of seven places:

1. const void *&transmogrify(void *&arg) {...}
The return value shouldn't be changed (which is rather pointless, since you return the pointer by value). This means that you can't cast it to a char * without casting away constness, a serious violation of design if you did. It usually indicates you have a pointer to something constant.

2. void const *&transmogrify(void *&arg) {..}
This is equal to the first.

3. void * const & transmogrify(void *&arg) {...}
This means that you can't change the pointer the function returns, but you can change the content of the pointer. The next line wouldn't compile:
transmogrify(NULL)++;

4. void *&transmogrify(const void *&arg) {...}
The function guarantees it won't touch the argument's content.

5. void *&transmogrify(void const *&arg) {...}
Same as 4.

6. void *&transmogrify(void * const &arg) {...}
The function guarantees it won't change your pointer but it might change the object being pointed at.

7. void *&transmogrify(void *&arg) const {...}
The function guarantees it won't change the object you call it on. This can only be done for non-static member functions.

Hope this gives a nice overview. Of course, if you have more than one pointer you can mess with it all you like, and you can combine the const examples above to give 72 possible combinations (in total), with 32 possible meanings.

For the const-win:

const object * const * const &func(const object * const, const int &) const {...}. If you get to this kind of stuff, wonder what the hell you're doing.

Re: c++ class inheritence

Posted: Wed Sep 19, 2007 1:01 pm
by Zacariaz
Solar wrote:
Zacariaz wrote:1. class King should be and exact copy of class Piece as it contain nothing more than the constructor call. Is this correct?
Yes.
Thank you.
Solar wrote:
3. Is there anyway to prevent other "users" of class Piece than class King?
You could keep the Piece header away from the public, but that isn't "secure" either, and for an "insecure" solution it should suffice to add a comment to the Piece header not to inherit from it.
ok, thats life...
Solar wrote:As nice as it is to see you have found an interesting project to test your C++ skills on, this is the umpteenth topic on this board about poker cards. Perhaps a single topic "Zacariaz' C++ Q&A" would be better.

And your examples could be a bit more... examplish. You know, class Base and class Child, no bitfields or program logic that has nothing to do with the subject. This is not due to a dislike towards poker, it just helps communication. It keeps people focussed on what you want to know, and usually helps you understanding the question better even before you post.

Oh, and your coding style is a bit hard to read. Most of the C++ code out there uses 4 space indents, spaces after ( and , as well as in front of ), and lists data members last in a class declaration. But that's only style, i.e. in the eyes of the beholder.

And while I'm nagging at banalities, another useful habit is to place the "const" always after the thing you're declaring const. In some places, you cannot put "const" first, and by putting it always last makes it more consistent.
ill remember the const thingy and about the other stuff... well, ill do my best to write better examples (i am not writing a chess engine), but about keeping it in one treat, of course if people agree ill try to do that, i my self find it more convinient to keep it in seperate threats.

Posted: Wed Sep 19, 2007 1:22 pm
by Zacariaz
JamesM wrote:Zacariaz: if you are implementing a chess engine, I would point you towards BitBoards (check wikipedia) as a useful implementation method. I personally didn't use them, and although my implementation is fast (ish), it can only do 8-9 plys in 10 seconds. It's competitive against GNU chess, although the lack of an opening book is to it's detriment :(
Im not at this time programing a chess engine, allthough i would like to, and have tried to do so before, but it was what i thought of for this little test of "skills" as solar wrote.

However i do agree that bitboards is worth considering. if you look at this again:

Code: Select all

typedef unsigned long long uint64;

class Piece {

        bool const Color:1;
        unsigned char Pos:6;

    public:

        Piece(bool const b,unsigned char const x,unsigned char const y):Color(b),Pos(x + (y * 8)) {}
        virtual ~Piece() {}

        uint64 getpos() const {return 1ull<<Pos;}

        bool move(char const x,char const y) {

            char const test = x + (y * 8) + Pos;

            if(test >= 0 && test < 64) {

                Pos = test;
                return 0;

            }

            else return 1;

        }

};
Youll see that i return a 64 bit integer in getpos(), coinsident? i think not ;)
anyway, i was just testing some stuff

Posted: Wed Sep 19, 2007 9:20 pm
by Colonel Kernel
Solar wrote:Foo const *, for example. Think about it. 8)

(Hint: What if you want the pointer to be constant, not the stuff it points to?)
Foo const * and const Foo * are equivalent. If I wanted the pointer to be constant, I'd write Foo * const. Where can I not do that?

Posted: Wed Sep 19, 2007 9:29 pm
by Alboin
Colonel Kernel wrote:
Solar wrote:Foo const *, for example. Think about it. 8)

(Hint: What if you want the pointer to be constant, not the stuff it points to?)
Foo const * and const Foo * are equivalent. If I wanted the pointer to be constant, I'd write Foo * const. Where can I not do that?
Wouldn't a constant pointer in C++ be a reference?

Posted: Wed Sep 19, 2007 10:13 pm
by Solar
Colonel Kernel wrote:Foo const * and const Foo * are equivalent. If I wanted the pointer to be constant, I'd write Foo * const. Where can I not do that?
You can write const Foo * (const leading) and Foo const * (const trailing) to make the stuff pointed to constant. But you can only write Foo * const (const trailing) to make the pointer const.
Alboin wrote:Wouldn't a constant pointer in C++ be a reference?
Kind of, yes, but I couldn't resist taking Colonel Kernel's expression as (simple) example. There are other places where const must trail (like the function declarations discussed above).

Posted: Wed Sep 19, 2007 11:07 pm
by Colonel Kernel
Solar wrote:You can write const Foo * (const leading) and Foo const * (const trailing) to make the stuff pointed to constant. But you can only write Foo * const (const trailing) to make the pointer const.
Oh, I get it now. You're choosing consistency over readability. ;)

To me "const Foo" makes a lot more sense than "Foo const", because grammatically, the adjective (const) modifying the noun (Foo) is supposed to precede it, not follow it. But then C++ is not exactly an intuitive language... This is the same reason I abhor things like "if (NULL == ptr)"... it reads like gibberish to me.

Posted: Wed Sep 19, 2007 11:56 pm
by Solar
Colonel Kernel wrote:Oh, I get it now. You're choosing consistency over readability. ;)
LOL... for me, consistency is readability. Mostly. I agree that a consistently leading "const" would be better, but so is life.
This is the same reason I abhor things like "if (NULL == ptr)"... it reads like gibberish to me.
ACK. I tend to go into berserk mode when I see this stuff, especially since every half-decent compiler spits a warning if you forget the second "=" these days.