I've been given a task for my cpp homework, the task is long and has many more functions that this, but I am stuck at the beggining. What I am trying to do here is just write out the point that is given on the screen.
#include <iostream>
using namespace std;
class Point {
public:
double x, y;
Point(){
x=0.0;
y=0.0;
};
Point(double x,double y){
this -> x = x;
this -> y = y;
}
void print() {
cout << "(x,y) = ("<< x <<","<< y <<")"<<endl;
}
};
class Triangle {
public:
Point A;
Triangle(const Point& p1){
A.x = p1.x;
A.y = p1.y;
}
void print1(){
cout << "A(x,y) = ("<< A.x <<","<< A.y <<")"<<endl;
}
};
int main(){
Triangle A{1.0,2.0};
A.print1();
return 0;
}
What my thinking here is, I have a class named Point and it is made of two variables x and y, class Triangle in the task has 3 points, but I am using just one for simplicity, it has a point that is from class Point (so it should have x and y coordinates) and a constructor that has a point from class Point also. I was thinking just to link their x and y coordinates and to print them out. But it doesn't work like that, can you help me. I have more code from the task if you need, and code from our lessons. Thank you.
Triangle(const Point& p1) accepts a const reference to a Point. A reference is an alias to an existing variable. In this case rather than copying in a Point, the Triangle constructor receives the Point itself. The const is important because it is a promise that the Point will not be modified inside by Triangle's constructor. This allows you to pass in a reference to a temporary Point that otherwise would not be around long enough for modification to be meaningful and is rejected by the compiler to prevent possible errors.
Triangle A{1.0,2.0};
will attempt to make Triangle from two floating point values. Triangle needs a reference to a Point, so you must make that Point first.
Triangle A{ {1.0,2.0} };
^ ^
| Construct a temporary Point from 2 floating point numbers
Triangle constructor arguments: one Point
Unrelated improvement: Use the Member Initializer List
Triangle(const Point& p1): A{p1}{
}
Related
I need to calculate the radius of the circle in the code.
#include <iostream>
#include <cmath>
using namespace std;
class Circle {
float radius;
const float PI=3.14;
public:
Circle(float radius){
}
Circle getRadius()
{
return radius;
}
Circle setRadius(float radius)
{
this->radius = radius / PI;
return radius;
}
float Area()
{
return radius*radius*PI;
}
float Perimeter()
{
return 2*radius*PI;
}
int equal()
{
return Area()==Perimeter();
}
};
int main() {
float r;
cin >> r;
Circle c(r);
cout << c.Perimeter() << endl;
cout << c.Area() << endl;
cout << c.equal() <<endl;
return 0;
}
i tried to use pointers but i cannot figure it out.
In
Circle(float radius){
}
a parameter with the same name as a member variable is not that member variable. Instead, it shadows the member variable, effectively replacing it unless you know where to look. Passing a value into a parameter named radius will not change the value of the member variable named radius, and this leaves the member radius uninitialized.
This means that
float Perimeter()
{
return 2*radius*PI;
}
and the other functions, excluding setRadius, operate on an uninitialized variable and the results will be undefined.
A possible solution is to ensure the member radius is initialized to the value of the parameter radius.
You cannot simply
Circle(float radius){
radius = radius;
}
because there is only one radius, the member has been shadowed, so the parameter radius assigns its value to itself. This is legal code so it compiles, but often the compiler will issue a warning.
Instead use
Circle(float radius) : radius(radius) {
}
This makes use of the Member Initializer List, one of the most important (and seemingly least-taught) features of the C++ programming language. It allows you to safely reuse the term radius because the first radius must be the member radius.
You could also
Circle(float radius) {
this->radius = radius;
}
to explicitly use the member radius, but for more complicated members this approach can be inefficient. All member variables and base classes are initialized before entering the body of the constructor. Afterward the best you can do is assign. This means the member will be default-initialized (if a default constructor exists; if it doesn't you must use the member initializer list), then a temporary variable must be constructed and this temporary is then assigned to the member. potentially a lot of extra work for no benefit.
Side note:
Keep an eye on the this->radius = radius / PI; in setRadius. It is unusual and probably a bug.
I have a 2d physics engine that I've been programming in C++ using SFML; I've implemented a rough collision detection system for all SandboxObjects (the base class for every type of physics object), but I have a dilemma.
I plan to have many different derived classes of SandboxObjects, such as Circles, Rects, and so on, but I want a way to check if the roughHitbox of each SandboxObject collides with another.
When the program starts, it allocates memory for, let's say, 10,000 Circles
int circleCount = 0;//the number of active Circles
constexpr int m_maxNumberOfCircles = 10000;//the greatest number of circles able to be set active
Circle* m_circles = new Circle[m_maxNumberOfCircles];//create an array of circles that aren't active by default
like so.
and every time the user 'spawns' a new Circle, the code runs
(m_circles + circleCount)->setActive();`
circleCount++
Circles that aren't alive essentially do not exist at all; they might have positions and radii, but that info will never be used if that Circle is not active.
Given all this, what I want to do is to loop over all the different arrays of derived classes of SandboxObject because SandboxObject is the base class which implements the rough hitbox stuff, but because there will be many different derived classes, I don't know the best way to go about it.
One approach I did try (with little success) was to have a pointer to a SandboxObject
SandboxObject* m_primaryObjectPointer = nullptr;
this pointer would be null unless there were > 1 SandboxObjects active; with it, I tried using increment and decrement functions that checked if it could point to the next SandboxObject, but I couldn't get that to work properly because a base class pointer to a derived class acts funky. :/
I'm not looking for exact code implementations, just a proven method for working with the base class of many different derived classes.
Let me know if there's anything I should edit in this question or if there's any more info I could provide.
Your problems are caused by your desire to use a polymorphic approach on non-polymorphic containers.
The advantage of a SandboxObject* m_primaryObjectPointer is that it allows you to treat your objects polymorphicaly: m_primaryObjectPointer -> roughtHitBox() will work regardless of the object's real type being Circle, Rectangle, or a Decagon.
But iterating using m_primaryObjectPointer++ will not work as you expect: this iteration assumes that you iterate over contiguous objects in an array of SandboxObject elements (i.e. the compiler will use the base type's memory layout to compute the next address).
Instead, you may consider iterating over a vector (or an array if you really want to deal with extra memory management hassle) of pointers.
vector<SandboxObject*> universe;
populate(universe);
for (auto object:unviverse) {
if (object->isActive()) {
auto hb = object -> roughtHitBox();
// do something with that hitbox
}
}
Now managing the objects in the universe can be painful as well. You may therefore consider using smart pointers instead:
vector<shared_ptr<SandboxObject>> universe;
(little demo)
It's hard to answer this without knowing the requirements but you could have sandbox maintain two vectors of active and inactive objects, and use unique_ptrs of the base class for memory management.
Some code below:
#include <vector>
#include <memory>
#include <iostream>
class sandbox_object {
public:
virtual void do_something() = 0;
};
class circle : public sandbox_object {
private:
float x_, y_, radius_;
public:
circle(float x, float y, float r) :
x_(x), y_(y), radius_(r)
{}
void do_something() override {
std::cout << "i'm a circle.\n";
}
};
class triangle : public sandbox_object {
private:
float x1_, y1_, x2_, y2_, x3_, y3_;
public:
triangle( float x1, float y1, float x2, float y2, float x3, float y3) :
x1_(x1), y1_(y1), x2_(x2), y2_(y2), x3_(x3), y3_(y3)
{}
void do_something() override {
std::cout << "i'm a triangle.\n";
}
};
class sandbox {
using sandbox_iterator = std::vector<std::unique_ptr<sandbox_object>>::iterator;
private:
std::vector<std::unique_ptr<sandbox_object>> active_objects_;
std::vector<std::unique_ptr<sandbox_object>> inactive_objects_;
public:
void insert_circle(float x, float y, float r) {
active_objects_.push_back( std::make_unique<circle>(x, y, r) );
}
void insert_triangle(float x1, float y1, float x2, float y2, float x3, float y3) {
active_objects_.push_back( std::make_unique<triangle>(x1,y1,x2,y2,x3,y3));
}
sandbox_iterator active_objs_begin() {
return active_objects_.begin();
}
sandbox_iterator active_objs_end() {
return active_objects_.end();
}
void make_inactive(sandbox_iterator iter) {
std::unique_ptr<sandbox_object> obj = std::move(*iter);
active_objects_.erase(iter);
inactive_objects_.push_back(std::move(obj));
}
};
int main() {
sandbox sb;
sb.insert_circle(10.0f, 10.0f, 2.0f);
sb.insert_triangle(1.0f, 1.0f, 2.0f, 2.0f, 2.0f, 1.0f);
sb.insert_circle(1.0f, 6.0f, 4.0f);
sb.make_inactive(sb.active_objs_begin());
(*sb.active_objs_begin())->do_something(); // this should be the triangle...
return 0;
}
This question already has answers here:
What is a debugger and how can it help me diagnose problems?
(2 answers)
What can cause segmentation faults in C++? [closed]
(9 answers)
Closed 2 years ago.
So I am writing a c++ OpenGl application that should test if two figures layed out with matches are identical. I have written an own class: the "figure" class. This class makes use of the two classes "Line" and "Point". Here you can see my implementation in the figure.h header:
#define SHINT short int
class Point
{
public:
std::pair<SHINT, SHINT> coord;
Point()
{
coord = std::pair<SHINT, SHINT>{ 0, 0 };
}
Point(int x, int y)
{
coord = std::pair<SHINT, SHINT>{ (short)x, (short)y };
};
};
class Line
{
public:
std::pair<Point, Point> pts;
Line()
{
pts = std::pair<Point, Point>{ Point(), Point() };
}
Line(Point p1, Point p2)
{
pts = std::pair<Point, Point>{ (Point)p1, (Point)p2 };
};
};
class Figure
{
public:
Figure() {};
private:
std::vector<Line> lines;
Point p1;
Point p2;
char* renderPath = FILEPATH;
public:
void DrawComponents();
void Clear();
void RemoveLine(int index);
void AddLine();
void SetWorking(int x, int y, bool segment); //true seg1, false seg2
void Render();
};
The implementation of the problematic functions are as follows:
void Figure::AddLine()
{
Line l1 = Line(p1, p2);
lines.push_back(l1);
}
void Figure::SetWorking(int x, int y, bool segment)
{
if (segment)
{
p1 = Point(x, y);
}
p2 = Point(x, y);
}
I have a fig*, that can be either set to the first figure or to the second Figure. You can do that with the help of an ImGui overlay. If you press your mouse button, a set of function is triggered:
selected->SetWorking(posX, posY, m_Select); //
if (m_Select)
selected->AddLine();
posX and posY are calculated relative to the mouse position and that is working properly.
We than call the SetWorking() function on the figure pointer, which again calls a constructor in the Point and Sets the working Point to what posX and Y are. I have to Points that are used in turns. So if I click the first time, the first Point is set, if I press a second time, the second Point is set, and with two Points set, we push a new line into the vector. This alteration is achieved by the "segment" bool int the SetWorking() function. Points are saved as std::pairs<> that hold short ints, and Lines are saved as std::pairs<> that hold two points. But if we land there, an error occurs: "Exception thrown: write access violation.
this was 0x14"
The error is thrown in the utility file of the c++ STL: (line 292)
pair& operator=(_Identity_t<_Myself&&> _Right) noexcept(
conjunction_v<is_nothrow_move_assignable<_Ty1>, is_nothrow_move_assignable<_Ty2>>) /* strengthened */ {
first = _STD forward<_Ty1>(_Right.first); // <---- here
second = _STD forward<_Ty2>(_Right.second);
return *this;
}
And honestly, at this point I don't have the slightest clue as of what is going on there. My educated guess is, that something with the std::pair is going wrong, but I am to unskilled with c++ yet, so I don't really now how to solve these kinds of error
"this was 0x14": The error occured in a member function (operator=()) of pair. The pair object that executes operator=() has a value of 0x14 for its this pointer, which is highly unlikely to be correct.
Usually this means that the pair is member of an object with this pointer == nullptr, and the pair object is located at offset 0x14 relative to the class.
I suspect that selected is a nullpointer and the assignment of p1 results in the access violation.
I was playing around with pointer to the base class, and I casted a rectangle pointer into a circle pointer and called the printradius() function from the rectangle! Could someone explain why this is allowed? Thanks.
#include <iostream>
#include <string>
using namespace std;
class Shape {
};
class Circle: public Shape {
private:
double radius;
public:
Circle(double r)
{ radius = r;}
void printradius()
{ cout << "circle's radius is " << radius << endl;}
};
class Rectangle: public Shape {
private:
double width, length;
public:
Rectangle(double l, double w)
{ length = l; width = w;}
};
int main() {
Rectangle r( 2.0, 2.0); // only a rectangle is created
Shape* s = &r; // up cast into a shape
Circle* c = static_cast<Circle*>(s); //down cast into a circle
c->printradius();
}
output:
circle's radius is 2
What do you mean by "allowed"?
The language explicitly states that the result of such static_cast is undefined, so it is not really "allowed" in this case. In order to perform a valid downcast from Shape * to Circle *, you have to ensure that Shape * actually points to Circle or something derived from Circle. Otherwise, the behavior is undefined.
As for why the compiler did not catch it... The compiler cannot possibly catch errors that depend on run-time conditions. In general case the compiler does not know what your s pointer actually points to.
As for why the language even offers such feature... It offers it because it can be extremely useful when one uses it properly.
The static cast is "because I said so.", in other words, trust me, the programmer, that the thing is what I say it is, a circle pointer in this case. When calling the printradius() method, The this pointer is for r, and when printradius() happens to deref looking for a radius, it finds that first double, with a value of 2.0. There is no crash, or reported error from running this way, but as you know, it makes no sense.
Use a dynamic cast and check the value returned. You will see null, because rectangle and circle are not the same.
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.