Trouble with classes

Hey
I was wondering if there is any way for me to use the "mass" variable from object.h in Mechanics.h ?
For example if I were to create an object called "ball" and wanted to calculate how fast it fell. I could initialize the mass but then I couldn't access it from the physics class "OPhysics" within "ball", and so would be unable to perform any calculations requiring it.

Mechanics.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
#ifndef MECHANICS_H_INCLUDED
#define MECHANICS_H_INCLUDED

# include <iostream>
#include <cmath>
class Physics
{
private:
    int PPosX, PPosY;
    int PVectX, PVectY;
    double PDisplacement, PDisplaceAngle;

public:
    Physics(int X= 0, int Y = 0):PPosX(X), PPosY(Y), PVectX(0),PVectY(0){}

    void ShowPos()
    {
        using namespace std;
        cout << "Current position is (" << PPosX << ", " << PPosY << ")\n";
    }

    void MovePos(int x , int y )
    {
        PVectX = x;
        PPosX += PVectX;
        PVectY = y;
        PPosY += PVectY;
    }

    void ShowDisplacement()
    {
        using namespace std;
        PDisplacement = sqrt((PVectX*PVectX)+(PVectY*PVectY));
        cout << "Displacement size = " << PDisplacement << endl;
        double angle = static_cast<double>(PVectX)/static_cast<double>(PVectY);
        cout << angle << endl;
        PDisplaceAngle = atan(angle)*  180 / 3.1415926;
        cout << "Displacement angle = " << PDisplaceAngle << endl;
        cout << "x = " <<  PVectX ;



    }
    
};

#endif // MECHANICS_H_INCLUDED


Object.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#ifndef OBJECT_H_INCLUDED
#define OBJECT_H_INCLUDED
#include "Mechanics.h"

class Object
{
private:
    int OMass;
    Physics OPhysics;
public:
        Object(int x = 0, int y = 0, int z = 0):OMass(x), OPhysics(y , z){}

    void Run()
    {
    OPhysics.ShowPos();
    OPhysics.MovePos(-4,3);
    OPhysics.ShowPos();
    OPhysics.ShowDisplacement();
    }
};
┬┐why do you need the mass for calculating free fall?

1
2
3
Object::some_action(params){
   OPhysics.calculation_that_uses_the_mass( this->mass );
}
You could create a function in Physics that has the value of mass passed to it, then stores it in its own variable (or not, depending on your purposes). Now... why do you need the mass? Falling objects in a vacuum fall at the same rate, regardless of mass.
In general, you should create an interface for your classes. That is, provide public functions that expose the variables you need to deal with.

Normally this would be with get / set functions. But don't overdo it - only provide what is necessary (only when the value of a variable needs to be available outside the class). Remember that class functions have direct access to member variables. Combine setting of several variables into 1 function where possible / logical. Keep in mind that variable are set initially with constructors, and you can provide output functions if all you want to do is print stuff.

Your Physics class is in the Mechanics header - that is confusing. Keep file names consistent with class names.

You also have implementation code in your headers which is evil. Implementation code (function definitions) go in their own .cpp file. Only the class declarations go in header files. This way, if a .cpp file needs to create / use an object of a particular type, it can just include it's corresponding header file.

HTH

Edit: You can rename your get / set functions logically as you have done with the MovePos function.
Last edited on
> provide public functions that expose the variables
You don't want to expose your variables.
The client code shouldn't be aware of your internal representation. That way you'll reduce coupling, making the code more flexible (more easy to modify)

> Normally this would be with get / set functions.
No. http://www.javaworld.com/javaworld/jw-09-2003/jw-0905-toolbox.html

> Your Physics class is in the Mechanics header - that is confusing. Keep file names consistent with class names.
There is no `one class per file' rule. But group them in a logical way.

> You also have implementation code in your headers which is evil.
Unless they are inline or template, having function definitions in headers will cause `multiple definition' error.
However,
1
2
3
4
class foo{
public:
   void bar(){} //implicit inline
};


Keep in mind that `#include' is simply copy-paste. If you put the definition in the header and later you change the implementation, the client code must be recompiled
Hey again,
Sorry for the late reply.

Thanks for all the advice guys but i still don't really understand what to do.

Firstly ill address some problems that have been pointed out.

I need the mass for any equation that determines acceleration. The ball dropping was just the simplest example i could think of. I realize this could change in a vacuum etc.
Ill also be changing the name of the header from Mechanics to physics.
I also realize i have included implementation code within the header file and it is bad. I'm going to change this later. I just left it there whilst i was checking the functions worked.

Next, even though i have just been advised against it, i don't understand how i could use the get/set functions to get data from the object file if OPhysics is created within. i don't know what the code should look like because the object would not have a name yet.
Would it just be
Object.Get()

Finally I recognize this probably wasn't the best way to do this in the first place so if possible would anyone be a able to suggest a better way of doing this.
My only requirements are:
The object has properties such as mass,size,friction coefficient etc
Physics perform actions on the object such as moving the position or applying a for.

Thanks again.







@ne555
You don't want to expose your variables.



> Normally this would be with get / set functions.

No. http://www.javaworld.com/javaworld/jw-09-2003/jw-0905-toolbox.html


But one should provide some sort of interface.

Scott Meyers talks about get / set functions in his book "Effective C++ 3rd Edition" Item 22 "Declare members Private" :

If you make data members public, everybody has read-write access to it, but if you use functions to get or set it's value, you can implement no access, read only access, and read write access.


However, he also said:

Such fine grained access control is important because many data members should be hidden. Rarely does every data member need a getter and setter.


I did say not to get carried away with getters / setters.

We had a discussion about this a while back. I was asking how to avoid having protected data (make it all private instead). cire was saying that base classes should have a complete interface so that variables in it can be set from a derived class. He also said that get / set functions increase encapsulation.

I can understand how having get / set functions can break code just the same as public / protected data, but I can't help thinking there are exceptions. And can the change in type be handled with templates - for example rectangle data changes from int to double.

Part of what I was asking in my post back then was about "Future Proofing" data. It seems to me that to do this effectively, one has to upgrade the variable to a class, or use a design pattern. Scott Meyers has examples about that. An example from your link:

Article wrote:
Today an "identity" is a name; tomorrow it's a name and ID number; the day after that it's a name, ID number, and picture.


This might be a bit much for a beginner - although it won't hurt to have it in mind.

What about all these questions:

Is it unreasonable to be able to enquire what a circle's radius is? Are length & size functions in the STL not getters? Is a move or rotate function in a drawing object class not a setter in disguise? How would you implement a move function otherwise? By template is still the same thing - a setter in disguise. What if I want to change only the Z value? I can think of lots of examples in geometry - another is draw a tangent line between point or circle drawing objects.

I should say that one has to be careful not to invalidate the other variables - for instance one shouldn't change the centre point of an arc without recalculating everything else. But that is the responsibility of any function doing any updating.

Article wrote:
Don't ask for the information you need to do the work; ask the object that has the information to do the work for you.


How does this work this situation using the physics scenario, where the work to be done is related to other objects as well:

Say we have 2 physical objects of different types which are subject to events that effect their velocity vectors (Direction & Speed). You want to calculate when & where they collide. To do this you must obtain the data from each object in order to make the calculation.

Whether another class is responsible for the calculation, or it is being done in one of the objects, or with a design pattern: there is no difference, one must "get" the data.

Is this scenario an exception to what is in the article?

There is no `one class per file' rule. But group them in a logical way.


OK, there is no hard rule about that - but I would strongly suggest that it certainly makes sense, and that it seems to be standard practice. If one has class declaration for classes A & B in 1 file, and that file is included somewhere - then you get both when you may have only wanted one. Having 1 per file with the same name is the most flexible & sensible IMO. Not having the same name really is confusing.


> You also have implementation code in your headers which is evil.

Unless they are inline or template, having function definitions in headers will cause `multiple definition' error.


I very much doubt if an experienced developer would put inline functions in a header, unless it was a very short explicit one - say with just a return statement - a getter?! . This all comes about because beginners see book authors lump all the code into 1 file - so they continue that idea until they learn otherwise.

Hopefully all this is not too much for the OP - there is often more than meets the eye with C++.
Hi jidder,

The object has properties such as mass,size,friction coefficient etc
Physics perform actions on the object such as moving the position or applying a for.


If all your objects behave the same way, then there would be no need for the physics class at all. Functions such as Move and ApplyForce would be part of the CPhysicalObj class, because they are directly related to it.

I named it CPhysicalObj to avoid confusion with meaning of a C++ object. I put a leading C on class names.

If the behaviour is different for each object, you could have an abstract (Interface, can't make an object) CPhysicalObj base class with pure virtual functions as an interface, from which concrete (can make objects) CPhysicalObj classes would derive. The virtual functions are redefined in the derived classes to reflect the individual behaviour.

Next, even though i have just been advised against it, i don't understand how i could use the get/set functions to get data from the object file if OPhysics is created within. i don't know what the code should look like because the object would not have a name yet.


Name functions like this in the class declaration:

double getMass();

Call the function through an object

1
2
3
CPhysicalObj MyObj;

double TheMass = MyObj.getMass();


When you say object file - do you mean a text file or get the data from a CPhysicalObj object?

HTH







I meant object class not file, i dont even know why i wrote that, sorry :)

Im probably just going to follow your advice and put the physics functions in the same class as the object properties for now as that does seem most practical at the moment.
There was a reason i didn't do that but I cant remember what it was so I'll just see how it goes.

Also, what i meant with the GetMass() function is that say i created an object called Ball
CPhysicalObj Ball
and then it had the Physics class within it, so it would look like
Ball.OPhysics
then within the Physics class i would not know the objects name in advance as it could be Ball or Shoe or MyObj etc.
so i wouldnt be able to write for example
1
2
3
4
5
6
void Freefall()
{
int Mass = Myobj.GetMass();
int Accel = Mass * -9.81;
...
}

as the object might not be called MyObj, it might be called Ball.

Sorry if that doesnt make sense.
I'm having trouble explaining it without showing you what i mean.

Thanks again.

Embedding an object of another type into a class is called composition (or aggregation), or class A "HAS A" class B object inside - the class B object is a member variable in class A. Composition is generally preferred over inheritance. Inheritance implies an "IS A" relationship. The other one is the "USES A" relationship where an object takes another object as an argument to one of it's functions.

Edit: Remember class functions have direct access to the member variables.

I am not sure why you would want composition of the physics class here. Composition of functions doesn't really make sense. Either put all the physics functions in the CPhysicalObj class, or have an abstract class like I mentioned earlier.

Where you would have composition is the example of a circle. It "HAS A" centre point class object, and a radius of type double say. Conversely, Circle does not inherit from Point, because a Circle IS NOT a Point. You can refer to the nested variable's functions by naming the objects with the dot notation:

double XOrdinate = MyCircle.CentrePoint.getX();

You should never have member variables public, so you shouldn't ever be able to refer to them with dot notation.

For inheritance, we could have a base class CFood, and a derived class CApple, because an apple "IS A" type of food.

For "USES A", we have an Arc - it might "USE" 3 points on the arc as arguments in it's constructor to determine the other necessary variables - Centre Point, Radius, StartAngle, EndAngle & NormalVector if it is 3D. Obviously this class "HAS" Point member variables as well.

Well, it's 03:00AM here - so I wish you well - I am going to stack ZZZZZzzzzz.....
Last edited on
Haha fair enough.

I just wanted to know how to do it if i needed to in the future really.Obviously didn't pick the best example though.

Im still not sure i fully understand but you have cleared a few things up.
Just gonna read through composition and inheritance again until i do.

Thanks for all the help though.
pass it as a parameter. void Freefall(int mass); or if you need void Freefall(Object &o);


@TheIdeasMan: http://www.ccs.neu.edu/research/demeter/demeter-method/LawOfDemeter/paper-boy/demeter.pdf
Also, think about the responsibilities of the object. As an exercise, write what you want the object to do, then decide which variables do you need.

> I very much doubt if an experienced developer would put inline functions in a header
You must put inline function definitions in a header. Otherwise you'll get `undefined reference'
I started a new thread about this:

http://www.cplusplus.com/forum/lounge/101305/


@ne555

> I very much doubt if an experienced developer would put inline functions in a header
You must put inline function definitions in a header. Otherwise you'll get `undefined reference'


I meant they would put most of their function definitions in the .cpp file, with the trivial explicit inline ones in the header file. I should have said
...would put implicit inline functions in the header ...


Also, think about the responsibilities of the object. As an exercise, write what you want the object to do, then decide which variables do you need.


Well, I already know how to do that 8+)

I also think about the interface, & get functions often form part of that (not always - only when necessary).

Functions like Move, Rotate, Scale & other update functions have the effect of setting / altering the data members, but I make sure that these have checking and validation in them - they are not trivial assignment functions.
@jidder

Well after 5 pages worth of discussion, we have arrived at something I now finally understand.

ne555 was right.

It would be good for you to read this & other posts in that topic if you haven't already seen it.

http://www.cplusplus.com/forum/lounge/101305/5/#msg546775
Topic archived. No new replies allowed.