I have a base class MovingObject defined like this:
class MovingObject
{
protected:
double x;
double y;
double speed;
double damage;
double distance(double x1, double y1, double x2, double y2)
{
return sqrt(pow(x1 - x2, 2) + pow(y1 - y2, 2));
}
public:
MovingObject(double x, double y, double speed, double damage);
virtual bool isCollide(MovingObject* Object);
virtual void draw() {};
virtual void move() {};
};
And I have 2 inherited classes from MovingObject class, Zombie and Bullet :
class Bullet : public MovingObject
{
private:
double dirX;
double dirY;
public:
Bullet(double x, double y, double speed, double damage, double dirX, double dirY);
bool isCollide(Zombie* pZombie);
void draw();
void move();
};
class Zombie : public MovingObject
{
private:
double hpMax;
double hpCurrent;
double attackCD;
double attackRate;
public:
Zombie(double x, double y, double speed, double damage, double hpMax, double hpCurrent, double attackCD, double attackRate);
bool isCollide(Bullet* pBullet);
void draw();
void move();
void getHit();
void drawHPBar();
void decreaseAttackCD();
void refreshAttackCD();
};
For example, lets say I want to check collision between Bullet and Zombie objects in the game. I want to check this collision in Bullet class like follows:
bool Bullet::isCollide(Zombie* pZombie) {
if (distance(x, y, pZombie->x, pZombie->y) < 10) {
pZombie->getHit();
return true;
}
else
return false;
}
But when I try to access the x and y attributes of Zombie in Bullet class, I can't access it. What I want to ask is, is it possible to check collision like this without using getX() and getY() functions ? I believe there is a flaw in my thinking because I am fairly new to C++ and OOP concepts. I do not want to full answer from you, I just want someone to point right path for me. Thank you in advanced.
Bullet cannot access Zobmbies protected members because it is not derived from Zombie. If you only need read access to x and y, you need constant getters in the MovingObject class.
class MovingObject
{
public:
double GetX() const { return x; }
double GetY() const { return y; }
protected:
...
};
and then use them in Bullet::isCollide()
if (distance(x, y, pZombie->GetX(), pZombie->GetY()) < 10) {
pZombie->getHit();
return true;
}
Please avoid using friend. With growing number of subclasses you will have to make them all friends.
Related
Suppose I have a simple class that defines a Circle object:
class Circle {
public:
Circle(const double x): radius(x) { ; }
const double getRadius() const { return radius; }
private:
const double radius;
};
This seems like a common convention and subscribes to the OO principle of data-hiding. My question is why do this? Would it not be simpler to make radius a public member? For a mutable member, this would obviously be a bad idea, since anyone could modify the circle's radius, but since it's const, I see no need to make it private. Would it be acceptable to do something like this?:
class Circle {
public:
Circle(const double x): radius(x) { ; }
const double radius;
};
I have this HW question that I have been stuck for hours on that I can't seem to make sense of. It's kind of hard to put to words my actual question but I will try my best. How can I make my outside-member function find the distance between a circle using a class which references another class? In my code below:
//Header
class Point
{
public:
Point();
Point(int, int);
Point(const Point& object);
int getX() const;
int getY() const;
void setX(int);
void setY(int);
double calculate_area();
void print() const;
private:
int x;
int y;
};
class Shape
{
public:
Shape();
double calculate_area();
void print() const;
protected:
double area;
};
class Circle : public Shape
{
public:
Circle();
Circle(const Point&, double);
double getRadius() const;
void setRadius(double);
void calculate_area();
void print() const;
private:
double radius;
Point center;
};
class RTriangle : public Shape
{
public:
RTriangle();
RTriangle(double, double);
double hyp();
void calculate_area();
void print() const;
private:
double side1;
double side2;
};
inline double distance(Circle& other)
{
return sqrt(pow(other.center.x, 2) + pow(other.center.y, 2));
}
#endif
//Implementation.cpp of what i think is important for you guys to see
Point::Point(int inX, int inY) // normal constructor
{
x = inX;
y = inY;
}
Point::Point(const Point &object) // copy constructor needed to use for center of circle
{
x = object.x;
y = object.y;
}
Circle::Circle(const Point& object, double inRad) // center is x & y... radius for circle
{
center = object;
radius = inRad;
}
My outside member function (inline double distance) isn't working. This is the first time I have tried doing this so I apologize if I do not word it well. I am essentially trying to use only the Circle class which inherits point center and point center is defined in the first class as x and y. Is it possible to do such a thing (specifically use x and y which is inside Point center)? I don't know if it's possible to access x and y through center.
Given a Point, functions not in Point can access its x and y members with the public getX() and getY() methods in your example.
However, Circle's center member is not public and has no public accessors. The most straightforward fix would add a public method
Point getCenter(); // or Point const &getCenter() if you like)
to Circle.
Here is my task:
Design classes Circle and Square which are inherited from class Shape (which contains center of gravity which is common characteristic for all shapes, function for moving center of gravity for specific value and virtual functions circumference, area and read). Classes should have specific functions for calculating circumference and area, as well as for reading data members.
Here is what I have done:
#include <iostream>
using namespace std;
class Point {
private:
float x;
float y;
public:
Point();
Point(float,float);
~Point();
};
Point::Point() {
}
Point::Point(float a,float b) {
x=a;
y=b;
}
Point::~Point() {
}
class Shape {
public:
Shape(void);
Shape(Point);
virtual float circumference(void) {}
virtual float area(void) {}
protected:
Point center_of_gravity;
};
Shape::Shape(void) {
}
Shape::Shape(Point a) {
center_of_gravity=a;
}
//----------------------------------------
class Circle:public Shape {
private:
float radius;
public:
float x;
float y;
Circle();
Circle(float);
virtual float circumference(void);
virtual float area(void);
};
Circle::Circle(void) {
}
Circle::Circle(float a) {
radius=a;
}
float Circle::area(void) {
float area_of_circle;
const float pi=3.14159;
area_of_circle=radius*radius*pi;
return area_of_circle;
}
float Circle::circumference(void) {
float circumference_of_circle;
const float pi=3.14159;
circumference_of_circle=2*radius*pi;
return circumference_of_circle;
}
//----------------------------------------
class Square:public Shape {
private:
float length;
public:
Square();
Square(float);
virtual float circumference(void);
virtual float area(void);
};
Square::Square(void) {
}
Square::Square(float a) {
length=a;
}
float Square::area(void) {
float area_of_circle;
area_of_circle=length*length;
return area_of_circle;
}
float Square::circumference(void) {
float circumference_of_square;
circumference_of_square=4*length;
return circumference_of_square;
}
int main() {
float a,b;
cout<<"Enter coordinates of center of gravity: "<<endl;
cin>>a>>b;
Point center_of_grav(a,b);
cout<<"Enter length of square: "<<endl;
cin>>a;
Square square(a);
cout<<"Enter radius of circle: "<<endl;
cin>>a;
Circle circle(a);
Shape *shape1=&circle;
Shape *shape2=□
cout<<"Area of circle is "<<shape1->area()<<", circumference is "<<shape1->circumference()<<endl;
cout<<"Area of square is "<<shape2->area()<<", circumference is "<<shape2->circumference()<<endl;
}
Is it ok? How can I realize function for moving center of gravity?
How can I read center of gravity for Circle and Square (it is inherited from class Shape)? They mean it (I think) when they say "...as well as for reading data members."
EDIT:
After I put all suggestion I got in one place:
#include <iostream>
using namespace std;
class Point{
private:
float x;
float y;
public:
Point();
Point(float,float);
~Point();
friend class Shape;
};
Point::Point(){
}
Point::Point(float a,float b){
x=a;
y=b;
}
Point::~Point(){
}
//----------------------------------------
class Shape{
public:
Shape(void);
Shape(Point);
virtual float area(void)=0;
virtual float circumference(void)=0;
protected:
float x_coordinate;
float y_coordinate;
Point center_of_gravity;
};
Shape::Shape(void){
}
Shape::Shape(Point a){
center_of_gravity=a;
x_coordinate=a.x;
y_coordinate=a.y;
}
//----------------------------------------
class Circle:public Shape{
private:
float radius;
public:
Circle();
Circle(Point,float);
virtual float area(void);
virtual float circumference(void);
};
Circle::Circle(void){
radius=0;
}
Circle::Circle(Point p,float a) : Shape(p), radius(a){
}
float Circle::area(void){
float area_of_circle;
const float pi=3.14159;
area_of_circle=radius*radius*pi;
return area_of_circle;
}
float Circle::circumference(void){
float circumference_of_circle;
const float pi=3.14159;
circumference_of_circle=2*radius*pi;
return circumference_of_circle;
}
//----------------------------------------
class Square:public Shape{
private:
float length;
public:
Square();
Square(Point,float);
virtual float area(void);
virtual float circumference(void);
};
Square::Square(void){
length=0;
}
Square::Square(Point p,float a) : Shape(p), length(a){
}
float Square::area(void){
float area_of_circle;
area_of_circle=length*length;
return area_of_circle;
}
float Square::circumference(void){
float circumference_of_square;
circumference_of_square=4*length;
return circumference_of_square;
}
//----------------------------------------
int main(){
float a,b;
cout<<"Enter coordinates of center of gravity: "<<endl;
cin>>a>>b;
Point center_of_grav(a,b);
cout<<"Enter length of square: "<<endl;
cin>>a;
Square square(center_of_grav,a);
cout<<"Enter radius of circle: "<<endl;
cin>>a;
Circle circle(center_of_grav,a);
Shape *shape1=&circle;
Shape *shape2=□
cout<<"Area of circle is "<<shape1->area()<<", circumference is "<<shape1->circumference()<<endl;
cout<<"Area of square is "<<shape2->area()<<", circumference is "<<shape2->circumference()<<endl;
}
1.Constructor design
How will you set their gravity center ?
Point center_of_grav(a,b);
...
Square square(c); // what's the gravity center ?
You have to design the constructor of the derived, so that it has all information required to construct the base:
Square square(center_of_grav, c);
To achieve this, you have to define it in the following way (of course adapt the class definition accordingly):
Square::Square(Point p, float a) : Shape(p), lentgh(a) {
// ... reserve this for more complex initisalisations
}
Note that your default constructor leave the objects uninitialized.
2.Design of Shape
Very important: Shape is a polymorphic class with virtual functions. You shall take the habit to define a virtual destructor in this case.
Minor remark: It makes no sense to create directely a Shape object. It's an abstract concept. There is no default rule to calculate an area or a circumference that could apply to most of the shape. Therefore, I'd strongly suggest to define these two functions as pure virtual:
class Shape {
...
virtual float circumference(void) =0; // pure virtual
virtual float area(void) = 0;
...
};
Advantage: as soon as you have a pure virtual function in a class, this class becomes abstract, and you won't be able to instantiate an object of that class by error. The compiler will make sure that you instatiate only concrete derivates of the abstract concept.
3.Make sure your code complies with requirements
Well it's a detail and you certainly have taken care of it, but:
Classes should have specific functions for calculating circumference
and area, as well as for reading data members.
So I think you should foresee some getters to access to the protected data:
Example:
class Shape {
...
Point get_gravity_center();
...
};
Point Shape::get_gravity_center() {
return center_of_gravity;
}
I let you complete the others. Simply imagine that you have to print in main() the description of a circle (coordinates of the center and radius), and you'll see the getters that are missing.
Edit following your question:
As you we've defined the getter for the center of gravity at the shape level, you don't need to define it again in the derivates. You could then simply call it in main(). The problem is that you also need to access to the coordinats of that point. So:
class Point {
...
float get_x() { return x; }
float get_y() { return y; }
...
};
With this you can write in main():
cout << "Circle of center ("<<circle.get_gravity_center().get_x()<<","
<< circle.get_gravity_center().get_y()<<")"<<endl;
P.S: with the center_of_gravity as member of shape, you no longer need to duplicate the coordinates otf that point.
To answer your question, it is not OK. Your code does show some pretty clear thinking, so that's good. It just needs to be finished. All data members of all classes must be given values when objects are constructed. Otherwise, they get random values, and that is never good practice. So init the CG in the Shape constructor.
Also, remove x and y from circle, if you mean them to represent CG -- that info is inherited already.
Finally, to realize a function for moving CG, I'd recommend adding a setter method to the Shape class, where it can be inherited by those other two classes. With that, you should be good to go.
I understand this isn't the best title but I'm not sure how to explain this problem that I'm having without examples.
I have a base class (called vector3)
class vector3 {
protected:
double x,y,z;
public:
vector3(): x(0),y(0),z(0) {}
vector3(double xin, double yin, double zin): x(xin),y(yin),z(zin) {}
~vector3() {}
//...other stuff
};
Then I have another class, derived from vector3, called vector4:
class vector4 : public vector3 {
protected:
double ct;
public:
vector4(): vector3(0,0,0), ct=0 {}
vector4(double ctin): ct(ctin) {}
vector4(double ctin, double xin, double yin, double zin):
vector3(xin, yin, zin), ct(ctin) {}
vector4(double ctin, vector3 v):
vector3(v.getx(), v.gety(), v.getz()), ct(ctin) {}
~vector4() {}
//...more other stuff
};
And that's all fine, but now I've got a class called particle defined like this:
class particle : public vector4 {
protected:
//vector4 r;
double mass;
//vector3 beta;
public:
particle(): vector4(0,0,0,0), mass=0, vector3(0,0,0) {}
particle(vector4 rin, double massin, vector3 betain):
vector4(rin.getx(),rin.gety(),rin.getz(),rin.getct()),
mass=0,
vector3(betain.getx(),betain.gety(),betain.getz()) {}
~particle() {}
//...Further stuff
};
So now the question is:
How do I return the x value, y value and z value of the particle's position, and the x value, y value and z value of the particle's beta vector inside a function in the particle class?
With vector 4 I'd just do:
double getx() const {
return x;
}
double gety() const {
return y;
}
etc, but what would I use in the particle's class?
Position and beta vector are attributes of a particle, so you should be using aggregation instead of inheritance:
class particle {
protected:
vector4 r;
double mass;
vector3 beta;
// ...
You should only use inheritance where there is an is-a relationship between the subclass and superclass.
In your case, particle is a vector4, so you can define your getters public in vector4, and directly call particle.getX()
However, this does not seem to be a good idea, in my opinion, particle should contain a vector since it is not a specialisation of the vector4 class.
so let's say particle has a vector called _vector
you can define a method like this :
double getX(void) const
{
return (_vector.getX());
}
Same goes for getY
I'm trying to inherit from one of my class 2 variables which they must be equal to be able to return the value of one of my functions in the other class..
class Rectangle: public Shape{
double Length;
double Width;
public:
Rectangle(double Length, double Width):
Shape("Rectangle")
{
this->Length=Length;
this->Width=Width;
}
double getPerimerter(){
return 2 * (Length+Width);
}
double getArea(){
return Length * Width;
}
};
class Square: public Shape, public Rectangle{
double Side;
public:
Square():
Shape("Square"),
Rectangle(Length,Width)
{}
double getPerimerter(){
if(Length==Width)
return 4 * (Length+Width);
}
double getArea(){
if(Length==Width)
return (Length+Width) * (Length+Width);
}
};
as you can see I have already a concrete class call Rectangle which hold to private variables with the names Length and Width.. What I'm trying to do is inherit this class to my class Square and if Length and Width are equal then I can return the Area and Perimeter of the Square..
It is perfectly fine to inherit from an existing class.
What you probably want, however, is this:
class Square: public Rectangle
{
public:
Square(double Side) : Rectangle(Side, Side) { }
};
That way, there is no problem of someone trying to use a ractangular square Square(4.3, 9.6).
Alternatively, you could of course use typedef Rectangle Square;
Edit:
To overcome the "name", we could do something like this:
class Rectangle
{
public:
Rectangle(double Length, double Width) : Shape("Rectangle") { ... }
protected:
Rectangle(double Length, double Width, const char *name) : Shape(name), Length(Length), Width(Width) {}
};
class Square
{
public:
Square(double side) : Rectangle(side, side, "Square") {}
};
Edit2: Code that I came up with:
#include <iostream>
using namespace std;
class Shape
{
private:
const char *name;
public:
Shape(const char *name) : name(name) {}
virtual double getPerimeter() = 0;
virtual double getArea() = 0;
};
class Rectangle: public Shape{
double Length;
double Width;
public:
Rectangle(double Length, double Width):
Shape("Rectangle")
{
this->Length=Length;
this->Width=Width;
}
double getPerimeter(){
return 2 * (Length+Width);
}
double getArea(){
return Length * Width;
}
protected:
Rectangle(double Length, double Width, const char *name):
Shape(name)
{
this->Length=Length;
this->Width=Width;
}
};
class Square: public Rectangle
{
public:
Square(double Side):
Rectangle(Side,Side, "Square")
{
}
};
int main()
{
Square sq(10.0);
Rectangle rect(12.0, 4.0);
cout << "sq:" << sq.getArea() << " rect:" << rect.getArea() << endl;
}
As a first thing you should add an argument to Square constructor, like so:
Square(double Side):Rectangle(Side,Side){
// Add additional constructor code here if required
}
About returning a value in a constructor - that is a no-go as the constructor might not return anything.
I hope this is what you meant as your question was quite hard for me to understand.
I might not understand your question, but it looks to me like you only need to add a parameter to your Square() constructor. It would look like this:
class Square: public Rectangle{
public:
Square(double dimension):
Rectangle(dimension, dimension){
}
};
There is no need for a conditional statement in the Square() constructor. Creating a Square necessarily implies creating a Rectangle with equal length and width.