Questions on Classes in C++

Started by
24 comments, last by Splinter of Chaos 15 years, 3 months ago
Hello im having Cpp problems with classes... I have over a year of Cpp and i just figured out what classes were 4 months ago(i know sad), and i was wondering if it was possible to change a value in an inherited class like:
[source lang = "cpp"]


// My block class
class Block
{
public:
    int blockX;
    int blockY;
    
    void draw()
    {
        //whatever you put in a draw funct
    }

    void move()
    {
        //whatever you put in a moving function
    }

    //other stuff goes here like funtions

};


// My bouncing ball class
class Ball
{
public:
    int ballX;
    int ballY;

    void draw()
    {
        //whatever you put in a draw function
    }

    void move()
    {
        //whatever you put in a moving function
    }

    //other stuff goes here like funtions

};


class MainProg : public Ball, public Block
{
public:
    int SomeMainValue;

    // collision funtion
    void collisions()
    {
        
        if( (ballY <= blockY + 10) && (ballY >= blockY - 10))
        {
            ballY -= 5;
        }
    }

    //other stuff goes here
};




// main////////////////////////////////////
int main()
{
    //Game engine setup, I use SDL...

    // load bmps...

    MainProg game;
    game.SomeMainValue = 5;


    Block paddle[2];
    for(int i; i <= 1; i++)
    {
        paddle.blockX = 5;
        paddle.blockY = 2;
    }


    Ball pongBall;
    pongBall.ballX = 10;
    pongBall.ballY = 5;


while(whatever = true)
{
    //sdl stuff

    paddle[0].draw();
    paddle[0].move();

    paddle[1].draw();
    paddle[1].move();


    pongBall.draw();
    pongBall.move();

    
    //to change values in both classes like movement
    game.collisions();

}

//sdl stuff

return 0;
}

If im doing something newbie tell me, and please give me a solution. The whole purpose of having the MainProg class is so that i can control values in other classes, but inheritence doesn't seem to let me do that... it just lets me have whatever is in the other two classes?(i think lol).. so please tell me if there is a way to change base values ( like in a collision funtion ) instead of changing values inherited. [Edited by - nuclearfission on January 7, 2009 11:43:56 PM]
Advertisement
First of all, reasonable people can (rarely) disagree, but you should avoid multiple inheritance--that is, a class shouldn't inherit both Block and Ball.

Secondly, inheriting both Block and Ball doesn't even make any conceptual sense... how can something be a block and a ball at the same time? Those are mutually exclusive "shapes". You shouldn't inherit things just to glue everything together, which seems to be what you're implying to be the motivation here. You inherit things because you need a "Cocker Spaniel" rather than a generic dog, or an "American Cocker Spaniel" rather than just a cocker spaniel.

Second of all, I'm not sure what you are asking exactly based on a quick glance at your source code. Rather, I'm not sure what it is that is and isn't working the way you expect. As a rule, though, if you need to be able to modify some internal value from outside of a class, you need to provide an interface to modify it. A method that takes inputs and acts accordingly.
It is posible to change a value in an iherited class The best practice way is to write a function in the inherted class to change the value.

In iheritance the class that iherates the other class gets a copy of alot of its things but you cant change values directly what you can do is use a virtual function so say something like this

class BASE{public:void ChangeNum(int ChangeTo){Num = ChangeTo;}private:int Num;};class DERIVED : public BASE{public:virtual void ChangeNum(int ChangeTo){};};


See when a class inherates the other the virutal funcs are overiden by the base class function so long as they are named the same and return the same kind of value. This is because all class virtual funcs are actualy stored in a virtual pointer table and overiden when nessicary.

Hope this helps and i hope i understood your question correctly.

I would agree with the above about multiple inheritance. Inheritance is powerful but should be used properly.

If there is something you had in mind lay it ouit first and plan out your code as it will become massivly easyer to code :)
Regards Jouei.
You seem to have a fairly deep misunderstanding of what classes and inheritance are used for, but this is nothing that some concentrated thought can't fix.

Quote:Original post by nuclearfission
The whole purpose of having the MainProg class is so that i can control values in other classes, but inheritence doesn't seem to let me do that... it just lets me have whatever is in the other two classes?(i think lol).. so please tell me if there is a way to change base values ( like in a collision funtion ) instead of changing values inherited.


An object is a conceptual entity that has a state and is able to perform actions that either modify this state or interact with other objects. A class is a template that specifies how a certain type of object could be made. An object created from a class is called an object of that class or an instance of that class. A class also introduces a new type into the type system in such a way that objects created from the class are assigned a type whose name is the same as the name of the class.

You are specifying two classes, Block and Ball. Any instance of Block should represent a conceptual entity that has the properties and behaviors of a block. Any instance of Ball should represent a conceptual entity that has the properties and behaviors of a ball.

Inheritance is a mechanism for creating new templates (or classes) for objects based on existing templates (or classes). A class that inherits from another includes all data and methods that the parent class(es) include and is able to expand on this by introducing new data and behavior. Inheritance is mostly used with the intention of combining it with type polymorphism.

You should always ask yourself this question when creating a new class that inherits from an existing class. Does the derived class describe a subset of all the objects representable by the parent class by adding special data and behavior in addition to that of the parent class to more accurately reflect this subcategory of objects?

If the answer to this question is negative, then you should almost always not use inheritance.

In this case, the question doesn't even make sense to ask! Is the main program a special type of block and ball? When stated this way, the entire design is just silly.

If you want to represent the main program as a class (which doesn't even appear necessary in this case; C++ does support an easy blending of procedural and object-oriented design paradigms), the block and ball should be instance variables (of type Block and Ball respectively) of the program class, not parent classes.

Happy coding!
Thank you guys for your replies, this cleared up some stuff and helped me out alot. I guess the whole purpose of a third class was that i was trying to "glue" in the other two. I'll try looking up on the web for "proper" ways of doing things.

Thank you guys alot [cool]
Hello nuclearfission,

When making your class (I've learned this through experience.) keep all your variables private.

For example in a 2D game you have a Ball which you wanted to change it's value you can do this:

Ball.h
#include <iostream>using namespace std;class Ball{private:	int x;	int y;public:	Ball(int xTemp, int yTemp);	void ChangeBallx(int xTemp);	void ChangeBally(int yTemp);	void ShowBallxy();	void DrawBall();};


Ball.cpp
#include "Ball.h"Ball::Ball(int xTemp, int yTemp): x(xTemp), y(yTemp){}void Ball::ChangeBallx(int xTemp){	x = xTemp;}void Ball::ChangeBally(int yTemp){	y = yTemp;}void Ball::ShowBallxy(){	cout << x << endl;	cout << y << endl;}void Ball::DrawBall(){	// Stuff}


main.cpp
#include <iostream>#include "Ball.h"using namespace std;int main(){	// Constructor	Ball RedBall(5, 6);	// Show X Y	RedBall.ShowBallxy();	cout << "\n\n\n";	// Change X Y	RedBall.ChangeBallx(19);	RedBall.ChangeBally(2);	// Show X Y	RedBall.ShowBallxy();	cin.get();	return 0;}


Now what you're doing here is keeping the variables private but you're using functions to change those variables for when you need. So if you wanted to keep setting a new location for x, y you would be able to do this easily with a function. Now, I personally believe in starting with constructors so I know everything that is made has something assigned. With the constructor you can set your starting position for your ball right off the bat. It's a good habit to always assign variables as soon as they're created, you will find out why when you use pointers.

Just encase you're not too familiar with what I did above, this is also valid.

main.cpp
#include <iostream>using namespace std;class Ball{private:	int x;	int y;public:        Ball(int xTemp, int yTemp): x(xTemp), y(yTemp)        {        }        void ChangeBallx(int xTemp)        {	        x = xTemp;        }        void ChangeBally(int yTemp)        {	        y = yTemp;        }        void ShowBallxy()        {	        cout << x << endl;	        cout << y << endl;        }        void DrawBall()        {	        // Stuff        }};int main(){	// Constructor	Ball RedBall(5, 6);	// Show X Y	RedBall.ShowBallxy();	cout << "\n\n\n";	// Change X Y	RedBall.ChangeBallx(19);	RedBall.ChangeBally(2);	// Show X Y	RedBall.ShowBallxy();	cin.get();	return 0;}


I hope I've been of some help.
Quote:Original post by nilkn
You should always ask yourself this question when creating a new class that inherits from an existing class. Does the derived class describe a subset of all the objects representable by the parent class by adding special data and behavior in addition to that of the parent class to more accurately reflect this subcategory of objects?

Wow, really? He has to ask himself that? No offense, but if he just recently started understanding classes, and considering what he is asking, do you really think that he is going to understand that question?

Quote:Original post by nilkn
You are specifying two classes, Block and Ball. Any instance of Block should represent a conceptual entity that has the properties and behaviors of a block. Any instance of Ball should represent a conceptual entity that has the properties and behaviors of a ball.

Yeah, this bit says exactly what you're looking for when wanting to know if you need to make a class derived from another class or not. It also pretty much describes what the higher block says, but it's easier to understand.

Quote:Original post by MrCpaw
When making your class (I've learned this through experience.) keep all your variables private.

Just wanted to let you know that although it is good practice in most cases, it is by no means concrete. The reason for keeping some member variables private is because nothing outside needs to access them and they are only used internally, in the class.

Others are that although the variables are supposed to be accessed and used a lot, when the variables are set, they need checking for invalid values, and sometimes they also need checking when you get the value of the variable.

These are only 2 reasons to keep variables private, but again, you might find a reason to make the variables public. If you do, then do it, don't think that you have to keep to that practice all the time.

It's better to break a common programming practice with a good reason and make the code better than keep the programming practice and have the code end up hacked or messy.
[size="2"][size=2]Mort, Duke of Sto Helit: NON TIMETIS MESSOR -- Don't Fear The Reaper
Quote:Original post by Endar
Quote:Original post by nilkn
You should always ask yourself this question when creating a new class that inherits from an existing class. Does the derived class describe a subset of all the objects representable by the parent class by adding special data and behavior in addition to that of the parent class to more accurately reflect this subcategory of objects?

Wow, really? He has to ask himself that? No offense, but if he just recently started understanding classes, and considering what he is asking, do you really think that he is going to understand that question?

Should != has to. While it may be a bit over his head, for now, too much information tends to be better than too little -- and if he *does* manage to digest it all, so to speak, he'll even have a head start on some good programming practices.

Quote:
Quote:Original post by MrCpaw
When making your class (I've learned this through experience.) keep all your variables private.

Just wanted to let you know that although it is good practice in most cases, it is by no means concrete. The reason for keeping some member variables private is because nothing outside needs to access them and they are only used internally, in the class.

Indeed: Keeping things private is the tool, not the goal. In MrCpaw's example, the setters encapsulate nothing, and cannot be imagined to maintain (or help to) any sort of invariant: One is only luring oneself into a false sense of security by making the variables private, if one then goes ahead and makes public functions with the exact same names (give or take a couple verbs) with the same types (as arguments) as in his example.
Quote:Original post by smitty1276
First of all, reasonable people can (rarely) disagree, but you should avoid multiple inheritance--that is, a class shouldn't inherit both Block and Ball.


I highly disagree that one should avoid multiple inheritance. While you're right, being a Block and Ball at the same time is a physical improbability, one can be movable, drawable, and inheriting from a base at the same time, calling this class Actor. And, although it sounds like Actor could just have a Mover and Drawer, the reason multiple inheritance is really nice there is they both require the use of data members from the base: position. Repetitive code--.

Quote:Original post by MaulingMonkey
Quote:Original post by Endar
Quote:Original post by nilkn
You should always ask yourself this question when creating a new class that inherits from an existing class. Does the derived class describe a subset of all the objects representable by the parent class by adding special data and behavior in addition to that of the parent class to more accurately reflect this subcategory of objects?

Wow, really? He has to ask himself that? No offense, but if he just recently started understanding classes, and considering what he is asking, do you really think that he is going to understand that question?

Should != has to. While it may be a bit over his head, for now, too much information tends to be better than too little -- and if he *does* manage to digest it all, so to speak, he'll even have a head start on some good programming practices.
Agreed, and let rephrase it instead of complaining about it, which is not helpful.

If class B inherits from class A, does it make sense that B is an A? As mentioned, it doesn't make sense for something to be a ball and a sphere, so this does not make sense.
"Is a" is an actually OOP term. There's also "has a". (google it).

But furthermore, if B is an A, is A not a B? And, what I mean by that is, is B in some way different than A for a reason other than different initializing values?

A common newbie abuse of classes:
    class A { int x,y; A(){ x=5;y=7; } };    class B : A { B() { x=8;y=2; } };
In this example, although B is an A, A is also a B.

Quote:
Quote:
Quote:Original post by MrCpaw
When making your class (I've learned this through experience.) keep all your variables private.

Just wanted to let you know that although it is good practice in most cases, it is by no means concrete. The reason for keeping some member variables private is because nothing outside needs to access them and they are only used internally, in the class.

Indeed: Keeping things private is the tool, not the goal. In MrCpaw's example, the setters encapsulate nothing, and cannot be imagined to maintain (or help to) any sort of invariant: One is only luring oneself into a false sense of security by making the variables private, if one then goes ahead and makes public functions with the exact same names (give or take a couple verbs) with the same types (as arguments) as in his example.

There seems to be a lot of disagreement about this. Some people seem to think public variables are unthinkable. I like things should be as public as possible, but I create getters or setters when either it's more convenient than accessing the variable, or accessing the variable from outside the class at the wrong time is in some way dangerous. When things are public, it's just easier.

EDIT:
What a man (or woman for all I know) much smarter (informed) than me thinks of multiple inheritance: http://www.parashift.com/c++-faq-lite/multiple-inheritance.html

[Edited by - Splinter of Chaos on January 7, 2009 1:47:13 AM]
Quote:Original post by Splinter of Chaos
I highly disagree that one should avoid multiple inheritance. While you're right, being a Block and Ball at the same time is a physical improbability, one can be movable, drawable, and inheriting from a base at the same time, calling this class Actor. And, although it sounds like Actor could just have a Mover and Drawer, the reason multiple inheritance is really nice there is they both require the use of data members from the base: position. Repetitive code--.
I didn't feel the need to confuse the OP with this, but allowing for interfaces (which may or may not meet your definition of multiple inheritance) I think eliminates any need to use true multiple inheritance.

Ignoring El Caminos for a second, assume it isn't possible to be both a car and a truck. Both can implement an IAutomaticTransmission interface, or both can have an AutomaticTransmission object.

Using your example, it would probably be considered--generally--more "correct" to have a class hierarchy that is along the lines of Entity->VisibleEntity->Ball and Entity->VisibleEntity->Block, which provides for all of your needs without the confusion of multiple inheritance.

EDIT: To respond to your edit Splinter, I agree that it is silly to declare multiple inheritance universally Bad. But I think 99% or developers would agree that it should be used only when absolutely necessary. Certainly a newcomer to OO design should be taught that it is less-than-preferable.

This topic is closed to new replies.

Advertisement