How do I properly access inherited methods and constructors in c++? - c++

I have a Sphere class which inherits a Point object for the center. When I create a Sphere object through the Sphere constructor, it always initializes the center to 0,0,0, but it will correctly set the radius.
Accessing the Sphere's setCenter() method also has no impact. The only way I can effectively change the X, Y, Z co-ordinates of the Sphere's center Point is to call the Point's setX() etc. methods.
I apologize if this is a blatantly obvious answer, but I'm new to C++ and struggling with the transition. If I've left out any important information, please don't hesitate to let me know. Here is the relevant code:
MAIN
#include <iostream>
#include <fstream>
#include "MovingSphere.h"
using namespace std;
int main() {
ifstream inFile("sphere.txt");
int X, Y, Z, R, DX, DY, DZ;
if (inFile) {
inFile >> X >> Y >> Z >> R
>> DX >> DY >> DZ;
}
else {
cerr << "\neRR: Cannot find input file.\n\n";
}
// create a sphere
Sphere sphereInstance(X, Y, Z, R);
sphereInstance.setCenter(1, 2, 3);
sphereInstance.setX(3);
cout << endl <<
"X = " << sphereInstance.getX() << endl <<
"Y = " << sphereInstance.getY() << endl <<
"Z = " << sphereInstance.getZ() << endl;
return 0;
}
Point.cpp
#include "Point.h"
Point::Point() : x(0), y(0), z(0) { // default constructor (point at 0,0,0)
}
Point::Point(int X, int Y) : x(), y(), z(0) { // constructor for 2d point
}
Point::Point(int X, int Y, int Z) : x(), y(), z() { // constructor for 3d point
}
// set the points X coordinate (mutator)
void Point::setX(int newX) {
x = newX;
}
... etc.
Point.h
#ifndef POINT_H
#define POINT_H
class Point {
public:
Point (); // default constructor (0,0,0);
Point(int X, int Y); // constructor for 2d point
Point(int X, int Y, int Z); // constructor for 3d point
void setX(int newX); // declaration
int getX() const; // declaration
etc...
private:
int x, y, z; // coordinates of point
};
#endif /* POINT_H */
Sphere.cpp
#define _USE_MATH_DEFINES
#include <math.h>
#include "Sphere.h"
Sphere::Sphere() :
center(), radius(0) {// default constructor (a point at 0,0,0)
}
Sphere::Sphere(int X, int Y, int Z, int R) { // sphere constructor
center = Point(X, Y, Z);
radius = R;
}
// set the sphere's center (mutator)
void Sphere::setCenter(int X, int Y, int Z) {
center.setX(X);
center.setY(Y);
center.setZ(Z);
}
... etc.
Sphere.h
#ifndef SPHERE_H
#define SPHERE_H
#include "Point.h"
class Sphere: public Point {
public:
Sphere(); // default constructor (a point at 0,0,0)
Sphere (int X, int Y, int Z, int R); // sphere constructor
void setRadius(int newRadius); // declaration
void setCenter(int X, int Y, int Z); // declaration
int getRadius() const; // declaration
private:
Point center; // center of sphere
int radius; // radius of sphere
};
#endif /* SPHERE_H */
The Output
X = 3
Y = 0
Z = 0

class Sphere: public Point {
This says a Sphere is a Point and starts with everything a Point has, including an X, Y, and Z coordinate.
private:
Point center; // center of sphere
This says a Sphere has a Point, called center. This Point that a Sphere has also has an X, Y, and Z coordinate, as all Points do.
So a Sphere both is a Point and has a Point, each with an X, Y, and Z coordinate. This can't be what you wanted, and your code fails when it sets one of these two Points and then gets the other.. Pick one model and stick to it.
If you need to treat a Sphere like a Point polymorphically, then remove center-- in this model, a Sphere is a Point that also has a radius. If you don't need to treat a Sphere like a Point, then don't inherit from Point -- in this model, a Sphere is not a point but has a Point and a radius.

Your Point 2 and 3 parameter constructors do nothing with the inputs. Change them to
Point::Point(int X, int Y) : x(X), y(Y), z(0) { }
Point::Point(int X, int Y, int Z) : x(X), y(X), z(Z) { }
If center is a Point data member of Sphere, then you should prefer initialization in the constructor initialization list rather than assignment in the body of the constructor:
Sphere::Sphere(int X, int Y, int Z, int R) : center(X,Y,Z), radius(R) { }
I edited a colon into the statement, but need at least 6 characters.

You don't show how Point and Sphere are related, but I guess that Sphere inherits from Point...
class Point
{
...
};
class Sphere : public Point
{
...
};
If you want to call e.g. the base constructor you do it in the initializer list:
Sphere::Sphere(int X, int Y, int Z, int R)
: Point(X, Y, Z), radius(R)
{
}
As for other functions, if they are in the base class you can use them as if they were member of the child class:
void Sphere::setCenter(int X, int Y, int Z)
{
setX(X);
setY(Y);
setZ(Z);
}
Since Sphere also is a Point (due to the inheritance) you don't need the center member variable.

As others have said, you should clarify exactly how Sphere is related to Point first (either Sphere has-a Point i.e. member, or Sphere is-a Point i.e. inheritance).
Your exact problem however is this:
Sphere's setCenter() method updates Sphere::center
Sphere uses Point's getX/Y/Z(), and these use the x/y/z in Point
That is, setCenter() updates things that have nothing to do with getX/Y/Z().

Related

C++ Error: "Multiple markers at this time: no matching function for call to" in constructor

Multiple markers at this line
- candidates are:
- no matching function for call to
'Coordinate::Coordinate()'
I am getting this error in the constructor of my class and I don't understand why. Here is the code involved:
RadialScan header
#ifndef RADIALSCAN_H_
#define RADIALSCAN_H_
#include "EasyBMP/EasyBMP.h"
#include <vector>
#include "Coordinate.h"
using namespace std;
class RadialScan {
vector<int> distanceTimeSeries;
vector<Coordinate> timeSeries;
BMP image;
Coordinate center;
Coordinate getNextPoint(Coordinate c);
bool isBlack(Coordinate c);
void computeTimeSeries();
public:
RadialScan(char* filename);
vector<int> getDistances();
vector<Coordinate> getCoordinates();
};
#endif
RadialScan class (all the methods are implemented, but the error is in the constructor and that's the code I'm providing):
#include "RadialScan.h"
RadialScan::RadialScan(char* filename){
image.ReadFromFile(filename);
int centerX = image.TellWidth()/2;
int centerY = image.TellHeight()/2;
center = Coordinate(centerX, centerY);
}
...
The error seems to be in the constructor. If I remove the constructor everything seems to compile correctly. If I delete the code inside the constructor I'm still getting the error. I don't understand why it keeps asking me for the Coordinate::Coordinate() constructor even when I don't have a coordinate object defined in the RadialScan(char* filename) constructor.
Additionally, these are the files for the Coordinate class:
header:
#ifndef COORDINATE_H_
#define COORDINATE_H_
class Coordinate {
int x;
int y;
public:
Coordinate(int x, int y);
void setX(int oneX);
void setY(int oneY);
int getX();
int getY();
double getMagnitude();
Coordinate operator-(const Coordinate&);
bool operator==(const Coordinate&);
Coordinate operator=(const Coordinate&);
};
#endif
cpp class:
#include "Coordinate.h"
#include <math.h>
Coordinate::Coordinate(int oneX, int oneY) {
x = oneX;
y = oneY;
}
//Setters
void Coordinate::setX(int oneX) {
x = oneX;
}
void Coordinate::setY(int oneY) {
y = oneY;
}
//Getters
int Coordinate::getX() {
return x;
}
int Coordinate::getY() {
return y;
}
double Coordinate::getMagnitude() {
return sqrt(x * x + y * y);
}
Coordinate Coordinate::operator-(const Coordinate& p) {
return Coordinate(x - p.x, y - p.y);
}
bool Coordinate::operator==(const Coordinate& p) {
return x == p.x && y == p.y;
}
Coordinate Coordinate::operator=(const Coordinate& p) {
return Coordinate(p.x, p.y);
}
Your constructor must look like
RadialScan::RadialScan(char* filename) : center (0, 0) {
image.ReadFromFile(filename);
int centerX = image.TellWidth()/2;
int centerY = image.TellHeight()/2;
center = Coordinate(centerX, centerY);
}
this because you did not implement default constructor and you can not create center object by default, so the only way is to call explicity Coordinate constructor with some default values.

Point, square, and cube program help on C++

I've been writing a program for CS class that's supposed to get the X and Y coordinates from the user, as well as the length of a square and the height of the cube, and it should then calculate the area of the square and the surface area and volume of the cube (plus some coordinates stuff but that's not a pressing issue right now)
I've written the test file and it compiled successfully, but I've been getting very long answers for the square and cube properties that are obviously wrong. Can anyone point out whatever logical errors I might have or if I have the access specification and relationship between the classes wrong?
Point.h
class Point
{
protected:
double Xint, Yint;
public:
Point();
void setX(double);
void setY(double);
double getX() const;
double getY() const;
};
Point.ccp
Point::Point()
{
Xint = 0;
Yint = 0;
}
void Point::setX(double x)
{ Xint = x; }
void Point::setY(double y)
{ Yint = y; }
double Point::getX() const
{ return Xint; }
double Point::getY() const
{ return Yint; }
Square.h
#include "Point.h"
class Square : public Point
{
protected:
Point lowerLeft;
double sideLength;
public:
Square(double sideLength, double x, double y) : Point()
{
sideLength = 0.0;
x = 0.0;
y = 0.0;
}
void setLowerLeft(double, double);
void setSideLength(double);
double getSideLength() const;
double getSquareArea() const;
};
Square.ccp
#include "Square.h"
void Square::setLowerLeft(double x, double y)
{
lowerLeft.setX(x);
lowerLeft.setY(y);
}
void Square::setSideLength(double SL)
{ sideLength = SL; }
double Square::getSideLength() const
{ return sideLength; }
// Calculate the area of square
double Square::getSquareArea() const
{ return sideLength * sideLength; }
Cube.h
#include "Square.h"
class Cube : public Square
{
protected:
double height;
double volume;
public:
Cube(double height, double volume) : Square(sideLength, Xint, Yint)
{
height = 0.0;
volume = 0.0;
}
double getSurfaceArea() const;
double getVolume() const;
};
Cube.ccp
#include "Cube.h"
// Redefine GetSquareArea to calculate the cube's surface area
double Cube::getSurfaceArea() const
{ return Square::getSquareArea() * 6; }
// Calculate the volume
double Cube::getVolume() const
{ return getSquareArea() * height; }
"Can anyone point out whatever logical errors I might have or if I have the access specification and relationship between the classes wrong?"
Well, from our well known 3-dimensional geometry a cube is made up from exactly 6 squares.
So how do you think inheriting a Cube class from a Square actually should work well?
You can easily define a Cube class by means of a fixed Point (e.g. the upper, left, front corner) and a fixed size of the edge length.
If you really want and need to, you can add a convenience function for your Cube class, that returns all of the 6 Squares it consist of in 3 dimensional space:
class Cube {
public:
Cube(const Point& upperLeftFrontCorner, double edgeLength);
std::array<Square,6> getSides() const;
};

C++ inheritance (overriding constructors)

I am learning OpenGL w/ C++. I am building the asteroids game as an exercise. I'm not quite sure how to override the constructors:
projectile.h
class projectile
{
protected:
float x;
float y;
public:
projectile();
projectile(float, float);
float get_x() const;
float get_y() const;
void move();
};
projectile.cpp
projectile::projectile()
{
x = 0.0f;
y = 0.0f;
}
projectile::projectile(float X, float Y)
{
x = X;
y = Y;
}
float projectile::get_x() const
{
return x;
}
float projectile::get_y() const
{
return y;
}
void projectile::move()
{
x += 0.5f;
y += 0.5f;
}
asteroid.h
#include "projectile.h"
class asteroid : public projectile
{
float radius;
public:
asteroid();
asteroid(float X, float Y);
float get_radius();
};
main.cpp
#include <iostream>
#include "asteroid.h"
using namespace std;
int main()
{
asteroid a(1.0f, 2.0f);
cout << a.get_x() << endl;
cout << a.get_y() << endl;
}
error I'm getting:
main.cpp:(.text+0x20): undefined reference to `asteroid::asteroid(float, float)'
You can use the : syntax to call the parent's constructor:
asteroid(float X, float Y) : projectile (x ,y);
Ok, just figured it out.
I actually don't have asteroid constructors defined because I thought they would inherit. But I think I have to do the following in asteroid.h:
asteroid(float X, float Y) : projectile(X, Y){];
You need a asteroid.cpp.
Even though inheriting from projectile, for non-default constructors (i.e., asteroid(float,float)), you still need to define the child class constructor.
You'll also need to define get_radius, as it's not defined in your base class.
Here's how that might look (I've taken the liberty of passing values for radius into both ctors):
#include "asteroid.h"
asteroid::asteroid(float r)
: projectile()
{
radius = r;
}
asteroid::asteroid(float x, float y, float r)
: projectile(x, y)
{
radius = r;
}
float asteroid::get_radius()
{
return radius;
}

c++: why 0 is displayed as 1.29571e+261

I am trying to create my first class in c++. I am making file called geometryitems.cpp and doing this:
using namespace std;
class Point
{
double x, y, z;
public:
// constructor
Point(double x, double y, double z)
{
}
// copy constructor
Point(const Point& pnt)
{
x = pnt.x;
y = pnt.y;
z = pnt.z;
}
void display()
{
cout << "Point(" << x << ", " << y << ", " << z << ")";
}
};
Then I call it from another file like this:
#include <iostream>
#include <cstdio>
#include "geometryitems.cpp"
using namespace std;
int main()
{
// initialise object Point
Point pnt = Point(0, 0, 0);
cout << "Point initialisation:" << endl;
pnt.display();
double t = 0;
cout << endl << t << endl;
Point pnt2 = pnt;
pnt2.display();
// keep the terminal open
getchar();
return 0;
}
Here is the output:
t is shown as normal 0 but other zeros are some other numbers. I would understand if they were just very-very small numbers but there are also very-very big ones...
Why are the zeros in Point shown as such strange numbers? Is there a way to make it looking as normal zeros?
You are not setting the member variables to any value in your constructor:
Point(double x, double y, double z)
{
}
You need
Point(double x, double y, double z) : x(x), y(y), z(z) {}
This initializes your data members x, y, and z using the constructor initialization list.
You should also remove your copy constructor. The compiler-synthesized one will do just fine.
It's empty
Point(double x, double y, double z)
{
}
So, Point pnt = Point(0, 0, 0); doesn't initialize anything. Use member initializer list. Also you can read more about it here.
Point(double x, double y, double z) : x(x), y(y), z(z)
{ //^^^^^^^^^^^^^^^^^^
// Initializer list
}
That copy-constructor is copying uninitialized values to another object.
Your constructor is buggy. The members aren't initialized. Change it to:
Point(double x_, double y_, double z_)
: x(x_), y(y_), z(z_)
{
}

C++ Sprite class with Vector Object as Member

Ok, I'm having this problem with my Sprite class. Basically the sprite class should have a object of class Vector as its member with Vector being a class with both angle and speed. The Vector class has a Vector(double,double) constructor so the speed and angle can be set at its initialization but when I make my sprite class. It sends an error that its calling Vector(), a blank constructor, and that it doesn't exist. I'm trying to figure out why its calling Vector(). Here is my code from both the Sprite and Vector classes.
#Vector.h
#ifndef VECTOR_H
#define VECTOR_H
class Vector
{
public:
Vector(double,double);
double getX();
double getY();
double getSpeed();
double getAngle();
void setSpeed(double);
void setAngle(double);
private:
double speed,angle;
};
#endif
#Vector.h
#include "SDL/SDL.h"
#include "vector.h"
#include "math.h"
Vector::Vector(double speed,double angle)
{
this -> speed = speed;
this -> angle = angle;
}
double Vector::getX()
{
return speed*cos(angle);
}
double Vector::getY()
{
return speed*sin(angle);
}
double Vector::getSpeed()
{
return speed;
}
double Vector::getAngle()
{
return angle;
}
void Vector::setAngle(double angle)
{
this -> angle = angle;
}
void Vector::setSpeed(double speed)
{
this -> speed = speed;
}
#Sprite.h:
#ifndef SPRITE_H
#define SPRITE_H
#include "vector.h"
class Sprite
{
public:
Sprite(int x,int y);
SDL_Rect getRect();
SDL_Surface* getImage();
void setRect(SDL_Rect);
void move();
void draw(SDL_Surface*);
private:
Vector movement;
double x,y,lastX,lastY,angle,speed;
SDL_Rect rect;
SDL_Surface* image;
};
#endif
#Sprite.cpp:
#include "SDL/SDL.h"
#include "sprite.h"
#include "functions.h"
#include <cmath>
Sprite::Sprite(int x, int y)
{
this -> x = x;
this -> y = y;
lastX = x;
lastY = y;
image = loadImage("box.png");
rect.x = x;
rect.y = y;
rect.w = image->w;
rect.h = image->h;
speed = 1;
angle = 0;
}
SDL_Rect Sprite::getRect()
{
return rect;
}
SDL_Surface* Sprite::getImage()
{
return image;
}
void Sprite::setRect(SDL_Rect rect)
{
this -> rect = rect;
}
void Sprite::move()
{
lastX = x;
lastY = y;
x += speed*cos(angle);
y += speed*sin(angle);
rect.x = int(x);
rect.y = int(y);
}
void Sprite::draw(SDL_Surface* dest)
{
blit(image,dest,int(x),int(y));
}
Your Sprite class has a Vector member that will be constructed when the Sprite is constructed. At the moment, the Vector will be initialized with the default constructor because you haven't specified otherwise. If you want a specific constructor of Vector to be used, you need to add an initialization list to the constructor of Sprite:
Sprite::Sprite(int x, int y)
: movement(1.0, 0.0)
{
// ...
}
This will initialise movement with arguments 1 and 0. In fact, you might as well add other members to your initialization list too:
Sprite::Sprite(int x, int y)
: movement(1.0, 0.0), x(x), y(y), lastX(x), lastY(y) // and so on...
{
// ...
}
The Vector is created in Sprite::Sprite(int x, int y). The blank constructor for Vector is called because you do not call a constructor in the initializer list: in fact, you leave the Vector movement completely uninitialized!
Do this:
Sprite::Sprite(int x, int y):
movement(3.14, 2.7)
{
...
}
to construct movement using a two argument constructor. I would pick better values than 3.14 and 2.7, those are just sample values.
I would also consider creating a public no-argument constructor on Vector for ease of use that initalizes speed and angle to zero.