C++ How do I create objects from different classes in another class? - c++

I have a program with two classes, one for points and one for a rectangle. I need to make two objects of point class within my rectangle class and make them private. I can't figure out how to use the rectangle constructor to make the points with the points constructor, every time I do so I get the error "no default constructor exists for class "Point2d"". Even when I make a default constructor I still get this. I'm at a loss here.
#include <iostream>
#include <cmath>
using namespace std;
class point2D {
private:
int x = 0;
int y = 0;
public:
int getX() {
return x;
}
int getY() {
return y;
}
point2D(int ax, int ay) {
x = ax;
y = ay;
}
};
class rectangleType {
private:
point2D p0;
point2D p1;
public:
int getX0() {
return p0.getX();
}
int getY0() {
return p0.getY();
}
int getX1() {
return p1.getX();
}
int getY1() {
return p1.getY();
}
int getWidth() {
return abs(getX1() - getX0());
}
int getLength() {
return abs(getY1() - getY0());
}
int getPerimeter() {
return 2 * (getWidth() + getLength());
}
int getArea() {
return (getWidth() * getLength());
}
rectangleType(int ax0, int ay0, int ax1, int ay1) {
point2D p0(ax0, ay0);
point2D p1(ax1, ay1);
}
};

Members and base classes not otherwise specifically initialized in the base+member initialization list require provision of default construction. In it's simplest form, given this:
class S
{
public:
S(int) {}
};
this is not possible:
S s;
because the only ctor (default copy-ctor notwithstanding) defined requires an int argument and none was provided. This is, perhaps, intentional by whomever designed S . It may not make sense to have an S without that require argument.
Carrying this forward to your specific circumstance, you have a class, point2D, whose only defined course of construction (default copy-ctor notwithstanding) is this:
point2D(int ax, int ay)
Like S in our previous example, this means something like this:
point2D pt;
is not possible. But that is exactly what is happening here (along with several other problems)
rectangleType(int ax0, int ay0, int ax1, int ay1)
// here, before entering the function body below, p0 and p1
// must be successfully constructed *somehow*
{
point2D p0(ax0, ay0);
point2D p1(ax1, ay1);
}
Before the constructor body is entered, all base classes (of which you have none), and member variables (of which you have two: p0 and p1), must be constructed. Since you are not directly initializing your p0 and p1 members in a member initialization list, the compiler attempts to find default constructors (takes no arguments, or has sufficient default values for all arguments declared). It can't find one. By providing a non-default ctor as you have, you've declared "this is the way these should be constructed". The compiler is therefor saying it could not find a way to create these things successfully.
In your case, providing such a constructor, while possible, isn't necessarily the proper (and certainly not the only) solution. Yes, you can, but it turns out all that does is enhance later issues. For example that will allow this to compile:
rectangleType(int ax0, int ay0, int ax1, int ay1)
{
point2D p0(ax0, ay0);
point2D p1(ax1, ay1);
}
But now you have another problem. Your members p0 and p1 are not the ones you see above. All the code above does is declare two more id's with the same names as your members (thereby shadowing the latter into obscurity), construct them, discard them on function exit, and ultimately leave you with your two members default-initialized, but not with the provided arguments. Shortly thereafter, you scratch your head and wonder went wrong.
You could still provide that default-ctor for point2D (which you didn't want to before, but now feel somewhat 'forced' to), and then do this:
rectangleType(int ax0, int ay0, int ax1, int ay1)
{
p0 = point2D(ax0, ay0);
p1 = point2D(ax1, ay1);
}
But now we're just piling on the rubbish, and an anti-pattern is forming. Now we're default-constructing our p0 and p1 members using a ctor we didn't think we needed (and perhaps even purposely didn't want), and then were discarding those efforts by constructing two more point2D objects and using copy-assignment to reap them.
There is a better way
Member Initialization
The language provides a way of telling telling the compiler, "before entering my constructor body, first construct my base class (if any) and members like this" :
rectangleType(int ax0, int ay0, int ax1, int ay1)
: p0(ax0, ay0)
, p1(ax1, ay1)
{
}
The syntax may seem a bit odd, but apart from the leading colon you've seen the rest before. In fact, you were even using it before in your prior code, but in the wrong place, and for the wrong target variables. This syntax says "construct these members like this, then enter the class constructor function body."
Another Example
That isn't the only place you can (or should) use this feature of the language. For example, your point2D constructor looks like this:
point2D(int ax, int ay)
{
x = ax;
y = ay;
}
But now you know you can also do this:
point2D(int ax, int ay)
: x(ax)
, y(ay)
{
}
Granted, it won't matter much, and any compiler with a grain of sanity will generate similar/identical code in the above trivial usage of this feature, but it stresses a larger overall theme. Where possible, use member-initialization lists to construct members. It is generally more efficient, and in many cases massively so.
A Special Note About Ordering
I mention this only because it is often relevant, ,and can be the cause of some interesting behavior you were otherwise not expecting. When using a member initialization list, the order of construction of the members is not dictated by the order of the list; it is dictated by the order of the member declarations. An example to show what I mean.
In your class, points p0 and p1 are declared in that specific order, top-down. Using our newly discovered member-initialization syntax, what happens when we do this (note the order in the list of members):
rectangleType(int ax0, int ay0, int ax1, int ay1)
: p1(ax1, ay1)
, p0(ax0, ay0)
{
}
This looks like p1 will be constructed before p0. That is not the case. The order of declaration in the class is what matters. Since the class as this:
private:
point2D p0;
point2D p1;
That means p0 will be constructed first, then p1, regardless of the order in the member-initialization list. This can lead to some interesting behavior, especially when you're not expecting it. In your trivial case it wouldn't overall matter, but it is worth noting nonetheless.

Your error tells you that you have to create a default constructor for the points class, e.g.
point2D() {}
or if you want to move the x & y initialization to the constructor
point2D()
: x { 0 }, y { 0 } {}
It happens because you've created a specialized constructor that takes two parameters. If not for that, the compiler would have generated a default constructor for you. :)
As for the initialization in the rectangle class try this:
rectangleType(int ax0, int ay0, int ax1, int ay1)
: p { { ax0, ay0 } }, p1 { { ax1, ay1 } } {}
Also, to remove redundant assignment (thanks #user4581301) you could transform your current 2D(int ax, int ay) into this:
point2D(int ax, int ay)
: x { ax }, y { ay } {}
Further reading:
https://en.cppreference.com/w/cpp/language/constructor (again thank you #user4581301)

your constructor should look like this:
rectangleType(int ax0, int ay0, int ax1, int ay1)
: p0 {ax0, ay0},
p1 {ax1, ay1}
{}
this is a member initialization list, you initialize values p0 and p1 by passing the arguments to their respective construcotrs

Related

Structure constructor in other structure

I am trying to create Voronoi diagram for some given points. Each points have different attributes and I want to denote it as color. To map my own Point structure with Boost Point concept, I have written some code. I have the following setup:
struct Point {
double a;
double b;
Point(double x, double y) : a(x), b(y) {}
};
// This Point structure is mapped to Boost Point concept. Code emitted
I have another structure as :
struct Point_Collection {
Point xy(double x, double y);
short color;
};
Visual Studio created an automatic definition as :
Point Point_Collection::xy(double x, double y)
{
return Point();
}
Now if I try to instantiate an object of Point_collection as:
std::vector<Point_Collection> *test;
test = new std::vector<Point_Collection>();
Point_Collection xy_color;
for (int i = 0; i < 5000; i++) {
xy_color.xy(rand() % 1000, rand() % 1000);
xy_color.color = rand() % 17;
test->push_back(xy_color);
}
I get an error.
error C2512: 'Point': no appropriate default constructor available
Can someone point me in the right direction why is this happening?
Point xy(double x, double y); declares a member function in Point_Collection that is identified by xy, accepts two doubles and returns a Point object by value.
If you want a simple aggregate that holds a point, the C++11 and onward way would be to define it like this:
struct Point_Collection {
Point xy;
short color;
};
Point_Collection xy_color{ { rand()%100, rand()%100 }, static_cast<short>(rand()%16)};
The above is a simple aggregate initialization using value initialization syntax. You should prefer it for two reasons:
It will not allow narrowing conversions. (Which int to short is, therefore the cast).
It's easy to implement. It requires no typing if your class has all public members.
(Also rand has better alternatives in C++11, check out the header <random>)
If you don't have access to C++11, then you can either write a constructor for Point_Collection.
struct Point_Collection {
Point xy;
short color;
Point_Collection(Point xy, short color)
: xy(xy), color(color) {}
};
Point_Collection xy_color (Point(...,...), ...);
Or use aggregate initialization with more verbose syntax:
struct Point_Collection {
Point xy;
short color;
};
Point_Collection xy_color = { Point(rand()%100, rand()%100), rand()%16 };
(Since the above is C++03, rand()%16 will be silently converted to short, despite it being narrowing).

dynamic cast fails on downcasting from parent to child

I have the following parent child simple classes:
class BoundBases{
public:
virtual ~BoundBases() { }
};
// Rectangular Bounds for tree
class RectBounds : public BoundBases{
public:
// x, y center point
double x, y;
double w, h;
~RectBounds(){ }
// (_x, _y): center of rectangle bound. (_w, _h): width and height
RectBounds(double _x, double _y, double _w, double _h){
x = _x;
y = _y;
w = _w;
h = _h;
}
//... more functions
};
I also have the following function structure:
void MyClass::init( BoundBases &bounds, std::vector<int> &colsPartitioned)
{
printf("init - new\n");
BoundBases * bPtr = &bounds;
RectBounds * rBounds = dynamic_cast<RectBounds *>(bPtr);
if(rBounds){
// do something
}else{
throw runtime_error("dynamic cast fail");
}
}
The dynamic cast is failing even though I call the function with RectBounds type as an argument. What is the reason?
FIXED:
The function calling init passed BoundBases by value, as follows:
MyClass2::MyClass2( BoundBases boundBases, std::vector<int> colsPartitioned) { // creates new table
// set up partition
partScheme_ -> setColsPartitioned(colsPartitioned);
partScheme_ -> setBoundBases(boundBases);
partScheme_ -> init(boundBases, colsPartitioned);
}
I changed the signature to pass by reference and it worked. (&boundBases). Can someone explain why is that? I am new to C/C++.
You need a reference here because dynamic_cast will only work if the real type of your variable is of type RectBounds like :
BoundBases* dummy = new Rectbound();
You can downcast here because the real type is Rectbound, so it will work.
If you pass it by value, it will create a copy of only the BoundBase part of your object, losing the information about your real type.
This problem is known as slicing
I'm not sure why you are surprised by that behavior. BoundBases passed by value is just a BoundBases. So dynamic_casting that to a child cannot make that a RectBounds. That's exactly what dynamic_cast is supposed to do.
If it worked differently: How would it be determining what e.g. x,y are if it's only given a BoundBases. This is not defined.

C++ confused with scope and declarations

I already posted another question regarding structs versus classes. I believe I got good feedback, so I went back to work on my code.
Here is what confused me (maybe it is childish ;) )
I need to Have a class (or struct doesnt really mind) that is called cPoint, and it just defines a Point in space with X, Y coordinates.
from it all shape-classes will derive. So for cRectangle, that is a class for rectangles, the cPoint will be used as a base element.
To instantiate a Rectangle, the caller must provide the coordinates of 2 points, that will be the rectangles UpperLeft & LoowerRight corners respectively.
What I want the cRectangle constructor to do, is to instantiate these two points, as it own private points and use them to define the rectangle, do calculations etc. These two points should not be visible to public scope, so a caller can't change them directly.
Here is an example(wrong obviously) for what I try to do:
class cPoint
{
public:
int X,Y;
cPoint();
cPoint(int x, int y)
{
X=x;
Y=y;
}
};
class cRectangle
{
friend class cPoint;
public:
Rectangle(int x1,int y1,int x2,int y2) //the constructor of cRectangle
{
ul(x1,y1);
dr(x2,y2);
}
unsigned int area()
{
return((dr.X-ul.X) * (dr.Y-ul.Y));//example function that uses ul,dr
}
private:
cPoint ul; //uP lEFT point
cPoint dr; //dOWN Right point
};
The error that i get is " Error 1 no match for call to '(cPoint) (int&, int&)' "
Thank you
/* use initilization list */
Rectangle(int x1,int y1,int x2,int y2) : ul(x1,y1), dr(x2,y2)
{
}
Your code won't compile because here
Rectangle(int x1,int y1,int x2,int y2) //the constructor of cRectangle
{
ul(x1,y1);
dr(x2,y2);
}
you wanted to call operator(int,int) on instances of cPoint class and definition of this operator has been not provided.
Once you enter the body of a constructor, all members are initialized and you can only assign to them and everything else that you can do to a living object.
By the point you attempt this
ul(x1,y1);
dr(x2,y2);
ul and dr have already been default initialized (default constructor is the one that's called if you don't explicitly initializer members - read on). When compiler sees these two lines, it looks like you're trying to call overloaded operator() that doesn't exist, so it naturally reports an error.
To initialize members, use constructor initialization list:
Rectangle(int x1,int y1,int x2,int y2)
: ul(x1,y1), dr(x2,y2) // <-- initialization list
// using cPoint::Cpoint(int, int) constructor
{
// note, empty body
}

C++ Passing an Object to a Member Function

For a homework assignment we are asked to create two classes: a MyPoint class and a ThreeDPoint class.
Here is my MyPoint class:
#pragma once
#include <math.h>
class MyPoint
{
private:
double x, y;
public:
MyPoint()
{
x = y = 0;
}
MyPoint(double x, double y)
{
this->x = x;
this->y = y;
}
double getX()
{
return x;
}
double getY()
{
return y;
}
double distance(MyPoint pointB)
{
return sqrt((x - pointB.x) * (x - pointB.x)
+ (y - pointB.y) * (y - pointB.y));
}
};
Here is my ThreeDPoint class:
#pragma once
#include "MyPoint.h"
class ThreeDPoint : public MyPoint
{
private:
double z;
public:
ThreeDPoint() // : MyPoint()
{
z = 0;
}
ThreeDPoint(double x, double y, double z) : MyPoint(x, y)
{
this->z = z;
}
double getZ()
{
return z;
}
double distance(ThreeDPoint pointB) // function overloading
{
// x and y are private not protected
return sqrt((getX() - pointB.getX()) * (getX() - pointB.getX())
+ (getY() - pointB.getY()) * (getY() - pointB.getY())
+ (getZ() - pointB.getZ()) * (getZ() - pointB.getZ()));
}
};
And here is main:
#include <iostream>
#include "SignatureBlock.h"
#include "MyPoint.h"
#include "ThreeDPoint.h"
int main()
{
SignatureBlock myBlock;
std::cout << myBlock.toString();
MyPoint pointA(1, 2);
MyPoint pointB(4, 2.5);
std::cout << pointA.distance(pointB) << '\n';
ThreeDPoint point_a(0, 0, 0);
ThreeDPoint point_b(10, 30, 25.5);
std::cout << point_a.distance(point_b) << '\n';
return 0;
}
This code works fine. It is able to calculate the distance between two points in both 2-dimensional and 3-dimensional space. However, in the homework instructions for the ThreeDPoint class, the book says to create
"A constant get function that returns the z value"
and
"A constant distance(const MyPoint&) function to return the distance between this point and the other point in three-dimensional space."
My question is what do they mean by "A constant get function..." and "A constant distance(const MyPoint&) function..."? I understand that you can put const after a function declaration to prevent the function from changing any class members, but why is this necessary here?
Also, why would I pass const MyPoint& to the distance function rather than a ThreeDPoint object? After all we're trying to find the distance between two ThreeDPoints. I read that if you have a parent object parameter in the member function declaration any child of that parent can also be passed to the function, so maybe that has something to do with it.
Lastly, isn't the distance(const MyPoint&) in the instructions missing a name for the MyPoint& object? I did try to type this in and the compiler doesn't mind, but how would I access the members of the object being passed in?
Edit: Also, what purpose does the & serve?
Most importantly, how would I re write my code to follow exactly what the instructions state?
Thanks for reading and thank you for any suggestions anyone might have.
If you live in a world where there are no const objects, it's never necessary to mark methods const. However, it is a good idea. Using const pointers and references is a very good practice when you don't need to change members of an object, and it can help you find design flaws when your program gets bigger.
It's also a good practice to pass references to objects, because passing a reference is usually faster than passing a copy of the object. (It's also in this context that you'll use const references: it tells the caller that you want the object by reference because it's faster, not because you want to change it.)
It's legal to omit argument names, but it has the obvious consequence that you won't be able to use them in your function. It's also a common notation because compilers get rid of argument names when they create function signatures, so you'll often see error messages that look like distance(const MyPoint&) instead of distance(const MyPoint& point).
I can't help you about why they want a const MyPoint& for the ThreeDPoint class. My best guess is that they want you to assume the z component of that point is 0.

C++ Rectangle Class clarification regarding syntax

I'll try to make this as concise as possible and while I understand that these questions can be considered "basic" I have already looked at websites such as cplusplus.com and yolinux tutorials but i need somebody to explain this to me like I have just had a major head trauma..
1)
class Rectangle {
private:
int lineNumber; // LineNumber of the ACSIL Tool
float valueMax; // value of the higher limit of the rectangle
float valueMin; // value of the lower limit of the rectangle
public:
Rectangle(SCStudyInterfaceRef sc, int lineNumber, float valueMax, float valueMin);
int getLineNumber();
float getValueMax();
float getValueMin();
};
So int linenumber, valueMax and ValueMin are declared private members and thus are only accessible by members of the same class, thats fine. But what about the part that follows the "public:" ?
a) Is Rectangle(SCStudyInterfaceRef sc, int lineNumber, float valueMax, float valueMin); a function that is being overloaded? and if yes are int getLineNumber() etc part of that function or seperate members of the public part of the class?
2)
Rectangle::Rectangle(SCStudyInterfaceRef sc, int lineNumber0, float value1, float value2) {
lineNumber = lineNumber0;
int value2_greater_than_value1 = sc.FormattedEvaluate(value2, sc.BaseGraphValueFormat, GREATER_OPERATOR, value1, sc.BaseGraphValueFormat);
if (value2_greater_than_value1 == 1) {
valueMax = value2;
valueMin = value1;
} else {
valueMax = value1;
valueMin = value2;
}
}
int Rectangle::getLineNumber() {
return lineNumber;
}
float Rectangle::getValueMax() {
return valueMax;
}
float Rectangle::getValueMin() {
return valueMin;
}
a) I'm pretty sure that the functions defined inside the public part of the rectangle class are being "defined" here, or something along those lines.
b) I am really confused about what is happening here on the Rectangle::Rectangle(SCStudyInterfaceRef sc, int linenumber0, float value1, float value2) part. I understand the logic of what is happening within the function itself but i am confused about the paramters being input within the " ( ) " and how exactly this relates to what happenes inside the class public part. This really is the most important question that needs answering.
I have tried to be as concise and onpoint as possible, would appreciate some help in understanding this syntax.
Question 1
It's a constructor with 4 parameters.
int getLineNumber();
float getValueMax();
float getValueMin();
are all member functions in the class.
Question 2
The constructor defined earlier is called with 4 parameters. If no other constructor is defined then you'll have to instantiate the class with exactly 4 parameters, i.e:
Rectangle *rect = new Rectangle(sc, 100, 1.2, 6.8);
or simply:
Rectangle rect(sc, 100, 1.2, 6.8);
These parameteres are then used to "set the object in an initial state".
The member functions are used to get various values in their current (or final or only) state.
Rectangle::Rectangle is the class constructor. It is called whenever a Rectangle object is created. Read about constructors to understand better.
The constructor is setting initial values for the valueMax and valueMin member variables. It uses the parameters passed to the constructor to do this. Read about function parameters to understand better.
1) a: If no ctor function is declared, then the compiler writes a ctor for the class. But when a ctor is provided by the class no default ctor is written by the class and hence no overloading is taking place. Now if you go on and define one more ctor, may be because you want the object to be constructed in some other way, then you will have an overloaded ctor. In your case no overloading is taking place.
int getLineNumber() is just another member of the class.
2)
a: You are correct.
b: The parameters put inside "( )" are arguments list and if this function is called somewhere, then this list is type-matched and then function is called(in case of overloading). Now if you write a statement like:
Rectangle x(a, b, c, d);
then it means that your sc=a, lineNumber0=b, value1=c, value2=d for this function call.