How do I switch this to unique_ptr? - c++

How do I make it so I dont have to manually delete the pointer?
With unique_ptr in the vector<> ?
Here is my code:
class vec2 {
public:
double x;
double y;
vec2() {
x = 0.0;
y = 0.0;
}
vec2(double xx, double yy) {
x = xx;
y = yy;
cout << "constructor called" << endl;
}
~vec2() {
static int count = 0;
cout << "destructor " << count << endl;
count++;
}
virtual double Length() { return sqrt(x * x + y * y); }
bool operator==(vec2& v) { return x == v.x && y == v.y; }
virtual string toString() {
stringstream s("");
s << "[" << x << " " << y << "]";
return s.str();
}
};
int main() {
vector<vec2*> vecs;
vecs.push_back(new vec2(1.8, 1.7));
vecs.push_back(new vec2(1.99, 1.7));
for (vec2* v : vecs) {
cout << v->toString() << endl;
delete v;
}
}
http://www.xgdev.com/notepad/textfiles/37631a.txt

Simple:
std::vector<std::unique_ptr<vec2>> vecs;
vecs.reserve(2); // Optional
vecs.push_back(std::make_unique<vec2>(1.8 ,1.7));
vecs.push_back(std::make_unique<vec2>(1.99, 1.7));
for (auto& v : vecs) {
cout << v->toString() << endl;
}
If you have virtual member function(s), most probably, destructor should also be virtual.

Related

I have a problem with my c++ code. Error is C2280

I have an error in my code, I want to display the sume of 2 objects with pointers in a class. Please help me to fix it, maybe is due to the pointers. Can you see what's wrong?
This is the error:
<source>(79): error C2280: 'Pair &Pair::operator =(const Pair &)': attempting to reference a deleted function
<source>(60): note: compiler has generated 'Pair::operator =' here
<source>(60): note: 'Pair &Pair::operator =(const Pair &)': function was implicitly deleted because 'Pair' has a user-defined move constructor
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
using namespace std;
class Pair {
int *x, *y;
public:
Pair() {
x = new int(sizeof(x));
y = new int(sizeof(y));
*x = 0;
*y = 0;
}
Pair(int a, int b) {
x = new int(sizeof(x));
y = new int(sizeof(y));
*x = a;
*y = b;
}
Pair(Pair& ob) {
x = new int(sizeof(ob.x));
y = new int(sizeof(ob.y));
*x = *(ob.x);
*y = *(ob.y);
}
Pair(Pair&& ob) {
x = new int(sizeof(ob.x));
y = new int(sizeof(ob.y));
*x = *(ob.x);
*y = *(ob.y);
}
Pair(int a):Pair(a, 0) {
}
void setX(int X) {
*x = X;
}
void setY(int Y) {
*y = Y;
}
int* getX() {
return x;
}
int* getY() {
return y;
}
~Pair() {
delete[]x;
delete[]y;
}
Pair sume(Pair ob1){
Pair ob2;
*(ob2.x) = *(ob1.x) + (*x);
*(ob2.y) = *(ob1.y) + (*y);
return ob2;
}
double media() {
return (double(*x) + double(*y)) / 2;
}
};
int main() {
Pair ob1, ob2(5), ob3(4, 3);
ob1.setX(6);
ob1.setY(7);
cout << "X= " << *(ob1.getX())<<endl;
cout << "Y= " << *(ob1.getY())<<endl;
cout << "Media este: " << ob1.media();
cout << "\nX= " << *(ob2.getX()) << endl;
cout << "Y= " << *ob2.getY() << endl;
cout << "Media este: " << ob2.media();
cout << "\nX= " << *(ob3.getX()) << endl;
cout << "Y= " << *(ob3.getY()) << endl;
cout << "Media este: " << ob3.media();
Pair ob4,ob5,ob6;
ob4 = ob1.sume(ob2);//here the compiler shows the error
cout <<"\nX= "<< *(ob4.getX())<<endl;
cout << "Y= " << *(ob4.getY())<<endl;
}

The problem approaching private number of class

My program receives width and breadth of rectangle
My output would be rectangle and specific point which can get from second line input. If number is odd , it will represent 'y' coordinate, else it will represent 'x' coordinate.
My problem is
pt.mark(pt.get_p(), pt.get_q());
this one.
In my method "mark",
buf << "+-" << setw(x() - 2) << "" << "-+" << endl;
x() represents " 0 " . So , my rectangle looks like
I don't know why this happen , because my approach to the private number of Class "Point" is not wrong using method x().
#include <iostream>
#include <string>
#include <vector>
#include <iomanip>
#include <sstream>
using namespace std;
class Point
{
private:
int _x, _y;
public:
Point(int x=0, int y=0): _x(x), _y(y) {}
int x() { return _x; }
int x(int n) {return _x = n;}
int y() { return _y; }
int y(int n) {return _y=n;}
};
class MovingPoint: public Point
{
private:
int p, q;
vector<int> nums;
public:
MovingPoint(int x = 0, int y = 0): Point(x, y) {}
MovingPoint(vector<int> a) : nums(a) {}
void mark(int x, int y);
void calculate();
int get_p() {return p;}
int get_q() {return q;}
};
ostream& operator <<(ostream& out, MovingPoint p)
{
return out << "(" << p.x() << ", " << p.y() << ")";
}
void MovingPoint::mark(int a, int b)
{
ostringstream buf;
vector<int> lengths;
vector<string> words;
int cnt;
char prev = buf.fill('-');
buf << "+-" << setw(x() - 2) << "" << "-+" << endl;
char pres = buf.fill(' ');
for (int i = 0; i < y() ; i++)
{
if (i == b - 1)
buf << "| " << setw(a) << "." << setw(x() - a) << " |" << endl;
else
buf << "| " << setw(x()) << " |" << endl;
}
char prev1 = buf.fill('-');
buf << "+-" << setw(x() - 2) << "" << "-+" << endl;
buf.fill(prev1);
cout << buf.str();
}
void MovingPoint::calculate()
{
p = 0;
q = 0;
for (int i = 0; i < nums.size() ; i++)
{
if (nums[i] % 2 == 0)
p++;
else
q++;
}
}
int main()
{
int x;
int y;
vector<int> nums;
cin >> x >> y;
MovingPoint pt(x, y);
while (cin >> x)
{
nums.push_back(x);
}
pt = MovingPoint(nums);
pt.calculate();
pt.mark(pt.get_p(), pt.get_q());
}
You might do, with some renaming:
#include <iostream>
#include <string>
#include <vector>
#include <iomanip>
#include <sstream>
struct Rectangle
{
unsigned int width;
unsigned int height;
};
struct Point
{
unsigned int x;
unsigned int y;
};
void draw(const Rectangle& rect, const Point& pt)
{
std::ostringstream buf;
buf.fill('-');
buf << "+-" << setw(x() - 2) << "" << "-+" << endl;
buf.fill(' ');
for (unsigned int i = 0; i < rect.height() ; i++)
{
if (i == pt.y - 1)
buf << "| " << setw(pt.x) << "." << setw(rect.width() - pt.x) << " |" << endl;
else
buf << "| " << setw(rect.width()) << " |" << endl;
}
char prev1 = buf.fill('-');
buf << "+-" << setw(rect.width() - 2) << "" << "-+" << endl;
buf.fill(prev1);
std::cout << buf.str();
}
Point calculate(const std::vector<int>& v)
{
Point p{0, 0};
for (auto e : v)
{
if (e % 2 == 0)
p.x++;
else
p.y++;
}
return p;
}
int main()
{
Rectangle r;
std::cin >> r.width >> r.height;
std::vector<int> nums;
int n;
while (std::cin >> n)
{
nums.push_back(n);
}
Point pt = calculate(nums);
draw(r, pt);
}

How to print two coordinates from class?

I have been trying to print the points like The position of the point is (1,2) from using class, but I can't figure out a way to do it. I simply can't find a way to return two numbers like that, but the problem requires solution that way.
#include <iostream>
using namespace std;
class MyPoint{
public:
int x,y,radius;
MyPoint()
{
x=0;
y=0;
}
MyPoint(int x1,int y1)
{
x=x1;
y=y1;
}
int point_display()
{
char st=(x,y);
return st;
}
int getAdd()
{
return x+y;
}
};
int main()
{
MyPoint mypoint;
cin>>mypoint.x>>mypoint.y;
cout<<"The position of the point is "<<mypoint.point_display()<<endl;
cout<<"The sum of the coordinates is "<<mypoint.getAdd()<<endl;
return 0;
}
The usual solution to this is to provide an overload of operator << for class MyPoint to print the point.
Something like this:
#include <iostream>
using namespace std;
class MyPoint{
public:
int x,y,radius;
MyPoint()
{
x=0;
y=0;
}
MyPoint(int x1,int y1)
{
x=x1;
y=y1;
}
int getAdd()
{
return x+y;
}
friend ostream& operator << (ostream& os, const MyPoint& p);
};
ostream& operator << (ostream& os, const MyPoint& p)
{
os << p.x << ", " << p.y;
return os;
}
int main()
{
MyPoint mypoint { 1,2 };
cout<<"The position of the point is "<<mypoint<<endl;
cout<<"The sum of the coordinates is "<<mypoint.getAdd()<<endl;
return 0;
}
Output:
The position of the point is 1, 2
The sum of the coordinates is 3
Live demo
Your point_display could return a string composed of the 2 values:
std::string point_display()
{
return std::string{"("} + std::to_string(x)
+ "," + std::to_string(x) + ")";
}
Alternatively, as your question asks about returning 2 values, the function could return a pair:
std::pair<int,int> point_display ()
{
return {x,y};
}
and in main, you could do:
auto [x, y] = mypoint.point_display();
cout << "The position of the point is ("
<< x << "," << y << ")" << endl;
However, since the data members are public, you could just destructure the object and print out the values in main:
auto [x, y, radius] = mypoint;
cout << "The position of the point is ("
<< x << "," << y << ")" << endl;
If all you want to do is print the coordinates, you could have the method do it:
void point_display()
{
cout << "(" << x << ", " << y << ")";
}
...
cout<<"The position of the point is ";
mypoint.point_display();
cout << endl;
If you really want to return the coordinates, you could have separate accessors ("getters"):
int getX()
{
return x;
}
int getY()
{
return y;
}
or use references:
void getCoordinates(int &rx, int &ry)
{
rx = x;
ry = y;
}
...
int a, b;
mypoint.getCoordinates(a, b);
cout << a << " " << b << endl;

apply_visitor does not change object

I have inherited from boost::static_visitor<> and defined a class as follows:
class move_visitor : public boost::static_visitor<> {
private:
double m_dx, m_dy;
public:
move_visitor() : m_dx(0.0), m_dy(0.0) {}
move_visitor(double dx, double dy) : m_dx(dx), m_dy(dy) {}
~move_visitor() {}
void operator () (Point &p) const {
p.X(p.X() + m_dx);
p.Y(p.Y() + m_dy);
}
void operator () (Circle &c) const {
Point center_point(c.CentrePoint().X() + m_dx, c.CentrePoint().Y() + m_dy);
c.CentrePoint(center_point);
}
void operator() (Line &l) const {
Point start(l.Start().X() + m_dx, l.Start().Y() + m_dy),
end(l.End().X() + m_dx, l.End().Y() + m_dy);
l.Start(start);
l.End(end);
}
};
This class is supposed to change the x and y position of some objects, Point, Line and Circle.
When I execute the following code:
int main()
{
typedef boost::variant<Point, Line, Circle> ShapeType;
Point p(1, 2);
Line l(p, p);
Circle c(p, 5);
ShapeType shape_variant;
std::cout << p << "\n\n"
<< l << "\n\n"
<< c << "\n\n";
shape_variant = p;
boost::apply_visitor(move_visitor(2, 2), shape_variant);
std::cout << p << std::endl;
shape_variant = l;
boost::apply_visitor(move_visitor(2, 2), shape_variant);
std::cout << std::endl << l << std::endl;
return 0;
}
p remains as 1, 2 and so does l. Why aren't my object changing after 'apply_visitor`?
You're modifying shape_variant, not p or l.
Try
std::cout << boost::get<Point>(shape_variant) << std::endl;
and
std::cout << boost::get<Line>(shape_variant) << std::endl;

Destructor problems+ list display [duplicate]

This question already has answers here:
What is The Rule of Three?
(8 answers)
Closed 7 years ago.
I have the following code:
The problem is when I create a list in main of type: Reteta.
After I display the list I receive am error of bad allocation. If I comment the destructor from the class Reteta the program works. Can you help me find the bug? Or maybe I didn't display the list well so the program have other problems to take care of.
Here is the code:
#include<iostream>
#include<fstream>
#include<list>
using namespace std;
class Medicament{
private:
char *denumire;
float pret;
public:
Medicament()
{
this->pret = 0;
this->denumire = new char[strlen("Fara denumire")];
strcpy(this->denumire, "Fara denumire");
}
Medicament(char* denumire, float pret)
{
this->denumire = new char[strlen(denumire) + 1];
strcpy(this->denumire, denumire);
this->pret = pret;
}
Medicament(const Medicament& x)
{
this->denumire = new char[strlen(x.denumire) + 1];
strcpy(this->denumire, x.denumire);
this->pret = x.pret;
}
~Medicament()
{
if (this->denumire)
{
delete[] this->denumire;
}
}
void setDenumire(char *x)
{
if (x)
{
if (this->denumire)
{
delete[] this->denumire;
}
this->denumire = new char[strlen(x) + 1];
strcpy(this->denumire, x);
}
}
char* getDenumire()
{
return this->denumire;
}
void setPret(float f)
{
if (f)
{
this->pret = f;
}
}
Medicament operator=(Medicament x)
{
this->denumire = new char[strlen(x.denumire) + 1];
strcpy(this->denumire, x.denumire);
this->pret = x.pret;
return *this;
}
friend ostream& operator<<(ostream& consola, Medicament &x)
{
consola << "Medicament: " << x.denumire << endl; //error here
consola << "Pret: " << x.pret << endl;
return consola;
}
float getPret()
{
return this->pret;
}
friend class Reteta;
};
class Reteta{
protected:
Medicament *medicamente;
int n;
public:
Reteta()
{
this->n = 0;
this->medicamente = NULL;
}
Reteta(Medicament *v, int n)
{
this->n = n;
this->medicamente = new Medicament[n];
for (int i = 0; i < n; i++)
{
this->medicamente[i] = v[i];
}
}
~Reteta()
{
if (this->medicamente)
{
delete[] this->medicamente; //The problem is here. If I comment this the program works.
}
}
int getN()
{
return this->n;
}
friend ostream& operator<<(ostream& consola, Reteta& x)
{
consola << "Numar de medicamente: " << x.n << endl;
consola << " -->Lista Medicamente<-- "<<endl;
for (int i = 0; i < x.n; i++)
{
consola << x.medicamente[i].getDenumire() <<endl; //error at this line when I compile
consola << x.medicamente[i].getPret()<< endl;
}
return consola;
}
void adaugaMedicament(Medicament x)
{
Reteta y;
y.medicamente= new Medicament[this->n+1];
for (int i = 0; i < this->n; i++)
{
y.medicamente[i] = this->medicamente[i];
}
y.medicamente[this->n] = x;
delete[] this->medicamente;
this->medicamente = new Medicament[this->n + 1];
this->n++;
for (int i = 0; i < this->n; i++)
{
this->medicamente[i] = y.medicamente[i];
}
}
Medicament operator[](int i)
{
if (i >= 0 && i < this->n)
{
return this->medicamente[i];
}
}
friend class RetetaCompensata;
virtual float getValoare()
{
float sum = 0;
for (int i = 0; i < this->n; i++)
{
sum=sum+this->medicamente[i].getPret();
}
return sum;
}
friend ifstream& operator>>(ifstream& consola, Reteta& x)
{
char aux[30];
float z;
consola >> x.n;
if (x.medicamente)
delete[] x.medicamente;
x.medicamente = new Medicament[x.n];
for (int i = 0; i < x.n; i++)
{
consola >> aux >> z;
Medicament m(aux, z);
x.medicamente[i] = m;
}
return consola;
}
};
class RetetaCompensata : public Reteta{
private:
float procentCompensat;
public:
RetetaCompensata(float procent)
{
this->procentCompensat = procent;
}
RetetaCompensata(Reteta r, float procent)
{
this->procentCompensat = procent;
this->n = r.n;
this->medicamente = new Medicament[r.n];
for (int i = 0; i < r.n; i++)
{
this->medicamente[i] = r.medicamente[i];
}
}
float getValoare()
{
float sum = 0;
sum = this->procentCompensat*this->getValoare();
return sum;
}
friend ostream& operator<<(ostream& consola, RetetaCompensata &x)
{
consola << "**Procent compensat: " << x.procentCompensat << endl;
consola << "Numar de medicamente: " << x.n << endl;
consola << " -->Lista Medicamente<-- " << endl;
for (int i = 0; i < x.n; i++)
{
consola << x.medicamente[i] << " ";
}
return consola;
}
};
void main()
{
//1
Medicament nurofen("Nurofen", 11.25f);
Medicament aspirina = nurofen;
aspirina.setDenumire("Aspirina");
aspirina.setPret(4.5f);
Medicament bixtonim("Bixtonim", 8.2f);
Medicament temp;
temp = nurofen;
cout << temp << endl;
cout << nurofen << endl;
cout << aspirina << endl;
//2
Medicament medicamente[] = { aspirina, nurofen };
Reteta r0(medicamente, 2);
cout << r0 << endl;
//3
Reteta r1;
r1.adaugaMedicament(nurofen);
r1.adaugaMedicament(aspirina);
for (int i = 0; i < r1.getN(); i++)
{
cout << r1[i] << endl;
}
//4
RetetaCompensata r2(0.5);
r2.adaugaMedicament(bixtonim);
r2.adaugaMedicament(aspirina);
RetetaCompensata r3(r1, 0.2);
cout << "AFISARE R3" << endl;
cout << r3 << endl << endl;
Reteta* p = &r1;
cout <<"Valoare reteta r1: "<< p->getValoare() << endl;
//5
Reteta r4;
ifstream fisier("retete.txt");
fisier >> r4;
cout << r4 << endl;
//6
cout << endl << "Afisare Lista :" << endl << endl << endl;
list<Reteta> R;
list<Reteta>::iterator it;
R.push_back(r0);
R.push_back(r1);
R.push_back(r3);
R.push_back(r2);
R.push_back(r4);
for (it = R.begin(); it != R.end(); it++)
{
cout << *it << " Valoare Reteta: " << it->getValoare() << endl << endl << endl; // error at this line when I compile
}
}
This is a memory overwrite:
this->denumire = new char[strlen("Fara denumire")];
strcpy(this->denumire, "Fara denumire");
You are not allocating room for the terminating null character:
this->denumire = new char[strlen("Fara denumire") + 1];
strcpy(this->denumire, "Fara denumire");
But why do this when you have std::string available? That alone not only alleviates errors like this, but you don't need to write assignment operators, copy constructor, or destructor for your Medicament class.
The other error is that your Reteta class lacks a copy constructor and assignment operator, thus it is not safely copyable due to the Medicament* member. You are then using this class as a type in std::list<Reteta>.
Since Reteta is not safely copyable, and std::list makes copies, you enter the world of undefined behavior. Thus you must provide appropriate copy / assignment operators for the Reteta class.