Declaring variables in derived classes + proper OOP

Started by
3 comments, last by Zahlman 18 years, 8 months ago
I'm working on a little game that has x numbers of computer/human players. I'm trying to do some proper OOP as I understand it and have a quick question about adding variables to these classes. I have a base class called 'Player' from which I derive two other classes, 'HumanPlayer' and 'AIPlayer'. I have created the 'Player' class with all the variables and functions that I feel a generic Player class should have. Now I'm finding that through the development of my game my derived classes need additional variables. Since both 'HumanPlayer' and 'AIPlayer' require the same variables I was wondering if I should just put them into my abstract class, 'Player', rather then adding the variables to both my 'HumanPlayer' and 'AIPlayer' class. Isn't it more correct to add the variables to my derived classes rather then modify my base Player class? Hopefully this makes sense. I'm trying to program correctly here, and not just what seems easier to me. Which in this case would be to add the variables to the 'Player' class and hence no need to declare them in my derived classes. Thanks.
Advertisement
One of the greatest uses of inheritance is the ability to make the compiler "write the code for you". In short you only write the one function, and all of your child classes inherit the code. This makes debugging vastly easier, as you need only debug the one function, not several near-identical versions.

Your base class should therefore contain every single common function and variable - as many as you possibly can.
only add those data to base class if only it's meaningful to all of the derive classes, otherwise the data mebers/functions should go to the derive where it only applies to that derive class. Put it where it would do the right thing.
Thanks for the help guys. Thats the way I wanted to do it, but wasn't sure how correct it would be.

Quiggy
Warning: If you assign from a derived object to a variable typed as a base object, you will lose the derived-object-specific data via the copy, as well as the objects "identity as derived" - C++ variables have types, which are not negotiable according to the assigned value. This is the hell of "object slicing", which is a source of many beginner complaints along the lines of "I made it virtual and it still isn't being polymorphic". Note that it happens at function boundaries too, an especially common way for beginners to mess it up.

The solution is to assign to (or pass as a parameter) a pointer - or pass by reference - instead; the pointer's size and behaviour is known, so there is no data loss, and the virtual-ness of the function will result in it behaving polymorphically when invoked through the pointer (you still have to mark the function virtual to get this effect though; otherwise the compiler generates the code to call the member function according to the pointer's static type, instead of generating code to check the type at runtime).

Passing by reference is easy to do. Basically, after indicating that you want a pass by reference, you use the variable as if it were a value (rather than a pointer), and the compiler will translate the code such that the value is referenced, a pointer is passed to the function, and then each use of the variable in the function implicitly dereferences that pointer and uses the result. This is cleaner (you don't have to think about the level of indirection), more expressive (for example, in C if you want a function to modify an argument that was already a pointer, you'd have to pass a pointer-pointer; in C++, you pass the pointer by reference, and the distinct roles of each level of indirection are clearly indicated), and safer (a reference cannot point to null or to an invalid object unless the code has *already* messed up, so a function receiving a reference need not check its validity; also, a reference cannot ever be re-pointed; only the pointed-at object could change) than using pointers.

If you would like to indicate that changes to the passed object should not be "seen" in the calling code (since passing by reference would allow that to happen; the passed in parameter is the "same object" inside the function as outside), you can mark it as 'const'. The compiler will then complain if you incorrectly do something that *does* modify the object (or appears to; const correctness is "viral" and there are a few things to learn :) ), preventing you from having to debug the problem at runtime.

This topic is closed to new replies.

Advertisement