Destroyer gets called right after constructor [closed] - c++

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 5 years ago.
Improve this question
i saw a few posts with same problem but i didn't not manage to understand how do i make the temporary object to constant
Map.H
#ifndef _Map_
#define _Map_
class Map
{
private:
int Board[7][7];
public:
Map();
Map(int mapNum);
~Map();
void print() const;
};
#endif
Map.Cpp basicly just creates a 7*7 array with 0 or 1 in all places
Robots.H
#ifndef _Robot_
#define _Robot_
#include "Map.h"
class Robot
{
private:
int _RobotID;
int _mapNum;
int _X;
int _Y;
public:
Robot();
~Robot();
Robot (int mapNum, int Line, int Column);
void setRobotID(int newid);
void print() const;
};
#endif
s
Robot.cpp
#include "Robot.h"
#include "Map.h"
#include <iostream>
#include "Game.h"
using namespace std;
Robot::Robot()
{
}
Robot::Robot(int mapNum, int line, int column) {
_mapNum = mapNum;
_X = line;
_Y = column;
_RobotID=0;
}
now creating a map in my main works and so does printing it.
same goes for robot.
what i want to do is connect the robot and the map inside my "game.cpp\game.h" so that each robot that i add will check in the map (double array with 0's or 1's )if it has a 1 it wont add it to map. and if it has a 0 it will.
(addRobot function is suppose to do that)
Game.H
#ifndef _Game_
#define _Game_
#include <vector>
#include <iostream>
#include "Map.h"
#include "Robot.h"
class Game
{
private:
static int _RobotsNum;
Map map1;
Map map2;
public:
void AddRobot(int mapnum, int x, int y);
Map getMap(int mapnum);
Game();
~Game();
};
#endif
Game cpp
#include "Game.h"
#include <algorithm>
#include <vector>
using namespace std;
int Game::_RobotsNum = 0;
vector <Robot> RobotVec;
Game::Game()
: map1(1),
map2(2)
{
}
Game::~Game()
{
}
void Game::AddRobot(int mapnum, int x, int y) {
my main
int main() {
Game game;
// Game* pgame = new Game();
game.AddRobot(1, 3, 4);
game.AddRobot(1, 4, 4);
game.AddRobot(1, 5, 4);
hope you guys can help me. thanks

This constructor has three local variables with the same names as other variables:
Game::Game()
{
vector <Robot> RobotVec; // Not your global variable
Map map1(1); // Not your member variable
Map map2(2); // Not your member variable either
}
In order to initialise members, you use the initialiser list:
Game::Game()
: map1(1),
map2(2)
{
}
In addRobot, this creates a robot and points X at it:
Robot* X = new Robot;
This also creates a robot, so now you have two:
Robot newRobot(mapnum, x, y);
And this memory leak points X away from its original robot and instead points it at newRobot, which will be destroyed immediately afterwards:
X = &newRobot;
Note that addRobot does not at any point add either robot to anything – it creates two and ignores them both.
You should make the vector a member (avoid global variables unless repeating other people's mistakes is a particular passion of yours):
class Game
{
private:
int robotsNum;
vector<Robot> robotVec;
Map map1;
Map map2;
// ...
};
Game::Game()
: robotsNum(0),
map1(1),
map2(2)
{
}
And add your new robot to the vector:
void Game::AddRobot(int mapnum, int x, int y) {
// ...
Robot newRobot(mapnum, x, y);
robotsNum++;
newRobot.setRobotID(robotsNum);
robotVec.push_back(newRobot);
}

Robot newRobot(mapnum, x, y);
This creates an object of type Robot named newRobot. At the end of the block where it was created it will be destroyed.

Related

Why Do I get this error on vector initialisation?

I have a problem with vector declaration and initialization in a
class constructor. I have a Station.h and Station.cpp files of a class and I recall it in main :
Station.h
#ifndef STATION_H
#define STATION_H
#include <vector>
class Station
{
public:
int num_bin;
int num_staz;
vector<int> binari; //here already gives me error! Vector does not name a type
Station(int num_staz, int num_bin);
virtual ~Station();
Station(const Station& other);
protected:
private:
};
Then I want to initialize the vector in the constructor of .cpp like that:
Station.cpp
#include "Station.h"
using namespace std;
Station::Station(int num_staz, int num_bin)
{
this->num_bin = num_bin;
this->num_staz = num_staz;
this->binari(num_bin); //here I want to create a vector of num_bin size
}
and then call it in main like that:
main.cpp
#include <iostream>
#include "Station.h"
using namespace std;
int main()
{
Station staz1(2,3);
staz1.binari.push_back(300); // error! class Station has no member binari
staz1.binari.push_back(250);
staz1.binari.push_back(150);
return 0;
}
Where am I making a mistake?
this->binari(num_bin); //here I want to create a vector of num_bin size
The function you need to use is std::vector::resize().
this->binari.resize(num_bin);
It will be better to initialize the object with the appropriate size as:
Station::Station(int num_staz, int num_bin) : num_bin(num_bin),
num_staz(num_staz),
binari(num_bin)
{
}
this->binari(num_bin); This doesn't work because it is not an initialization that is why it doesn't work.
To make this work use it in in-class initialization list:
Station::Station(int num_staz, int num_bin) :
num_bin(num_bin),
num_staz(num_staz),
binari(num_bin)
{
}

FLTK C++ Fl_line don't draw

I was tasked to debug a code that was meant to draw a simple polygon out of 4 points using FLTK. The MyWindow class derive from Fl_Window. The Shape class is the parent class for ClosedPolyline. Both MyWindow and Shape hold a vector to draw all of the shapes.
The problem is that after compiling and run, win.show() opens an empty window without any drawing. I'm puzzled to understand this behavior.
Here is the code (I've omitted some of the parts that are not related to drawing ClosedPolyline):
#include <iostream>
#include <FL/Fl.H>
#include <FL/Fl_Draw.H>
#include <FL/Fl_Window.H>
#include <FL/Fl_Widget.H>
#include <FL/Fl_Device.H>
#include <initializer_list>
#include <vector>
#include <functional>
//#include <cmath>
//#include <math.h>
struct Point {
int x,y;
Point(int xx, int yy) : x(xx), y(yy) { }
};
class Shape{
public:
Point point(int idx) const {
return (points[idx]);
}
unsigned int points_size() const {
return points.size();}
void draw() /*const*/{
draw_lines();
}
void add(Point p){ points.push_back(p); }
protected:
virtual void draw_lines() {}
private:
std::vector<Point> points;
};
class ClosedPolyline: public Shape {
public:
/*ClosedPolyline(std::initializer_list<Point> pp) {
if (pp.size() > 0) {
for (Point p: pp)
add(p);
}
}
*/
ClosedPolyline(Point a1, Point a2, Point a3, Point a4){
add(a1); add(a2); add(a3); add(a4);
}
protected:
void draw_lines() override{
for (unsigned int i=1; i<points_size(); ++i){
fl_line(point(i-1).x, point(i-1).y, point(i).x, point(i).y);
}
}
};
class MyWindow: public Fl_Window {
public:
MyWindow(int x, int y, int w, int h, const char* title = 0)
: Fl_Window(x, y, w, h, title) {}
void Attach(Shape s) {
shapes.push_back(&s);
}
//void draw_shapes(){draw();}
protected:
void draw() override{
for(Shape * s: shapes) {
s->draw();
//s.draw();
}
}
private:
std::vector<Shape*> shapes;
};
And here is the main() function:
int main() {
MyWindow win(100, 100, 600, 400, "C++ Test task");
ClosedPolyline p{Point{100, 100}, Point{100, 200}, Point{500, 100}, Point{500, 200}};
win.Attach(p);
win.end();
win.show();
return (Fl::run());
}
Lets take a look at your MyWindow::Attach function:
void Attach(Shape s) {
shapes.push_back(&s);
}
In the function, the argument s is passed by value. That means it's the same as a local variable inside the function. And as such it will go out of scope and be destructed once the function return.
Saving a pointer to that variable will lead to you saving a stray pointer, pointing to a non-existing object. Dereferencing that pointer will lead to undefined behavior, turning your whole program ill-formed and invalid.
One way to solve the problem is to make sure that the object don't go out of scope. This can be done by using smart pointers like e.g. std::unique_ptr. And to use it from the beginning already when you define the variable p in the main function.
Another way to solve your problem is to assume that the Shape passed to Attach will have a lifetime that outlives the Shape object, and you could therefore pass the Shape by reference:
void Attach(Shape& s) {
shapes.push_back(&s);
}
Now you no longer get a copy of the Shape object, and push a pointer to the original object (in your case the object p in the main function). Dereferencing the pointer will be valid as long as the original object is alive and in scope.
I try run that code in VS2015 and get a lot of error( of course fix attach window pass by reference ) But when I run to linux , it can draw, So I think you should move to linux.

C++ Polymorphism issues. Something to do with _vfptr

I am trying to create a program that has the user click twice on the screen and a rectangle is drawn according to what was clicked.
Right now all I am trying to do is set my classes up to be able to correctly draw a rectangle manually without worrying about where the user clicks.
Eventually my program will be able to draw stuff like circles and triangles so I decided to use Polymorphism and have each shape type (i.e. Rectangle) be its own class that inherits from a class called Shapes.
I then have a class called Game which holds a Shapes object.
Shapes.h
#ifndef _shapes_h_
#define _shapes_h_
#include <vector>
#include "glut.h"
class Shapes
{
public:
void DrawAll() const;
void Add(Shapes * shape);
virtual void Draw() const {}
protected:
std::vector<Shapes *> mShapes;
};
#endif
Shapes.cpp
#include "Shapes.h"
#include <iostream>
void Shapes::DrawAll() const
{
int i;
for (i = 0; i < mShapes.size(); i++)
{
mShapes[i]->Draw();
}
}
void Shapes::Add(Shapes * shape)
{
mShapes.push_back(shape);
}
Rectangle.h
#ifndef _rectangle_h_
#define _rectangle_h_
#include "Shapes.h"
class Rectangle : public Shapes
{
public:
Rectangle(std::vector<int> p1, std::vector<int> p2);
void Draw() const;
private:
std::vector<int> mP1;
std::vector<int> mP2;
};
#endif
Rectangle.cpp
#include "Rectangle.h"
#include <iostream>
Rectangle::Rectangle(std::vector<int> p1, std::vector<int> p2)
{
mP1 = p1;
mP2 = p2;
}
void Rectangle::Draw() const
{
std::cout << "Draw Me " << std::endl;
glColor3d(0, 0, 0);
glBegin(GL_QUADS);
glVertex2d(mP1[0], mP1[1]);
glVertex2d(mP2[0], mP1[1]);
glVertex2d(mP2[0], mP2[1]);
glVertex2d(mP1[0], mP2[1]);
glEnd();
}
Game.h
#ifndef _game_h_
#define _game_h_
#include <vector>
#include "Shapes.h"
class Game
{
public:
void Click(int x, int y);
void Draw();
private:
Shapes mTest;
};
#endif
The first Game.cpp below is coded in a way of what I am trying to do, but it throws me the error Unhandled exception at 0x001AF742 in Shapes.exe: 0xC0000005: Access violation reading location 0x00000001. After looking into this, I've found that some __vfptr hidden pointer variable (that I think controls virtual stuff) gets set to 0 and causes memory issues.
Note, Click() only gets called when the mouse is pressed, Draw() is called anytime any type of event happens (e.i. mouse press, mouse release, key press, key release etc.) When the mouse is pressed, both events get called, but Click() gets called first.
Also, mTestis the variable that is the Shapes object.
Game.cpp: Doesn't Work
#include "Game.h"
#include "Rectangle.h"
#include <iostream>
void Game::Click(int x, int y)
{
std::vector<int> p1;
p1.push_back(200);
p1.push_back(200);
std::vector<int> p2;
p2.push_back(250);
p2.push_back(250);
Rectangle rect(rp1, rp2);
Shapes * rectangle = &rect;
mTest.Add(rectangle);
}
void Game::Draw()
{
mTest.DrawAll();
}
However, what seems to baffle me is if I add a Shape Rectangle to mTest inside of the Draw() function right before I call DrawAll(), it works. However, I want to be able to create the Rectangle depending on where the User clicks, and this method wont allow that.
Game.cpp: Works
#include "Game.h"
#include "Rectangle.h"
#include <iostream>
void Game::Click(int x, int y)
{
}
void Game::Draw()
{
std::vector<int> p1;
p1.push_back(200);
p1.push_back(200);
std::vector<int> p2;
p2.push_back(250);
p2.push_back(250);
Rectangle rect(rp1, rp2);
Shapes * rectangle = &rect;
mTest.Add(rectangle);
mTest.DrawAll();
}
In Shapes class replace
std::vector<Shapes *> mShapes;
by
std::vector<std::shared_pointer<Shapes>> mShapes;
Than replace code
Rectangle rect(rp1, rp2);
Shapes * rectangle = &rect;
mTest.Add(rectangle);
by
mTest.Add(std::make_shared<Rectangle>(rp1, rp2));
And finally replace method definition
void Shapes::Add(Shapes * shape)
by
void Shapes::Add(std::shared_ptr<Shapes> shape)
It makes your code works.
Summary: If you need pointers, think about smart pointers (std::unique_ptr mentioned by #user657267 is smart pointer too). You can read about smart pointers in many places, here and here. For better design, do not forget for design patterns.

Issue with forward declaring class

So I am trying to forward declare a class in my C++ project and then create it in main.
So I have player_obj.cpp which contains the class, classes.h which forward declares the class, and main.cpp which uses it.
classes.h
#ifndef CLASSES_H
#define CLASSES_H
class player_class
{
public:
int x;
int y;
char sprite;
int xprevious;
int yprevious;
private:
bool active;
public:
void update_xy();
player_class(int _x, int _y, char _sprite);
void step();
void destroy();
};
#endif
main.cpp
#include <iostream>
#include "classes.h"
using namespace std;
int main()
{
player_class player_obj (5,5,'#');
cout << player_obj.x << ", " << player_obj.y << endl;
return 0;
}
and player_obj.cpp
#include <iostream>
#include <Windows.h>
using namespace std;
class player_class
{
public:
//Coordinates
int x;
int y;
//Sprite
char sprite;
//Previous coordinates
int xprevious;
int yprevious;
//Not everyone can set the activity
private:
//Active
bool active;
//Update xprevious and yprevious - Called by the step event
void update_xy()
{
xprevious = x;
yprevious = y;
}
//All functions public
public:
//Create event/Constructer
player_class(int _x, int _y, char _sprite)
{
//Set default variables
x = _x;
y = _y;
sprite = _sprite;
xprevious = x;
yprevious = y;
active = true;
}
//Step event
void step()
{
//Update old xprevious and yprevious
update_xy();
//Do other stuff here
}
//Drestroy event
void destroy()
{
active = false;
}
};
I thought that would work out all right but when I compile and run it I get:
main.cpp:(.text+0x2c): undefined reference to`player_class::player_class(int, int, char)'
I've done some research, but I can't seem to fix this issue.
I greatly appreciate any help!
Well you're sort of close, what you have in your header is indeed a class declaration (not a forward declaration mind you).
The problem is you never defined it. What you have in player_obj.cpp is an abomination of class redefinition, but you already have your class declared. Just include the header file and define the functions one by one and you're done!
#include "classes.h"
player_class::player_class(int _x, int _y, char _sprite)
{
//Set default variables
x = _x;
y = _y;
sprite = _sprite;
xprevious = x;
yprevious = y;
active = true;
}
// and so on
If you're serious about learning modern C++ though, a few notes:
#pragma once is the modern way of guarding header files. Don't use those #ifdef..#endif constructs.
generally speaking, don't name anything starting with underscores. Especially not parameters visible as part of your public contract.
you have class initializers for a reason, use them! You don't need half a screen of copy pasting variables in your constructors.
You dont want a forward declaration. You want a declaration. It is a classical case of declaring a class in a header file and defining its functions in a cpp file. Then including the header where-ever you want to use your class
You only need forward declarations when you want to use a pointer to that class as a parameter to a function or a member variable somewhere but the definition of that class is not available yet.
Note that when you forward declare a class, you cannot use this class's member variables or functions in that header
-regards
Gautam

modifying an object's std::vector from within another class

Intro:
In my program, a group object has an std::vector full of polygons (a ring and holes) and a polygon object has an std::vector of points. In reality, the classes are more complicated, I've stripped them down here to illustrate my problem.
The problem:
I want to be able to modify the point's x and y coordinates from within it's corresponding group object. Below, in group.cpp, I have a dummy function called void Group::tryChangingAllX() that tries to accomplish this. However, calling show() on the group afterwards shows no change to it's polygon's point's coordinates.
I think I need to use references/pointers, but I need a nudge in the right direction.
point.cpp:
#include "point.h"
#include <iostream>
Point::~Point(){}
Point::Point(int x, int y){
_x = x;
_y = y;
}
void Point::show(){std::cout << "(" << x() << "," << y() << ")";}
void Point::x(int x){_x = x;}
void Point::y(int y){_y = y;}
int Point::x(){return _x;}
int Point::y(){return _y;}
point.h:
#ifndef POINT_GUARD
#define POINT_GUARD
class Point{
int _x;
int _y;
public:
Point(int x, int y);
~Point();
void show();
int x();
int y();
void x(int x);
void y(int y);
};
#endif
polygon.cpp:
#include "polygon.h"
#include "point.h"
#include <iostream>
#include <vector>
Polygon::~Polygon(){}
Polygon::Polygon(){}
std::vector<Point> Polygon::points(){return _points;}
Polygon::Polygon(std::vector<Point> points){_points = points;}
void Polygon::show(){
std::cout << "Points: ";
for(std::vector<Point>::size_type i = 0; i != _points.size(); i++) {
_points[i].show();
}
}
polygon.h:
#ifndef POLYGON_GUARD
#define POLYGON_GUARD
#include <vector>
#include "point.h"
class Polygon{
//private:
std::vector<Point> _points;
public:
~Polygon();
Polygon ();
Polygon(std::vector<Point> points);
std::vector<Point> points();
void show();
};
#endif
group.cpp:
#include <iostream>
#include <vector>
#include "group.h"
#include "polygon.h"
Group::~Group(){}
Group::Group(std::vector<Polygon> polygons){
_ring = polygons.front();
polygons.erase(polygons.begin());
_holes = polygons;
}
void Group::tryChangingAllX(){
std::vector<Point> points = _ring.points();
for(std::vector<Point>::size_type i = 0; i != points.size(); i++) {
points[i].x(15);
}
}
void Group::show(){
_ring.show();
if(_holes.size()>0){
for(std::vector<Polygon>::size_type i = 0; i != _holes.size(); i++) {
_holes[i].show();
}
}
}
group.h:
#ifndef GROUP_GUARD
#define GROUP_GUARD
#include <vector>
#include "polygon.h"
class Group{
Polygon _ring;
std::vector<Polygon> _holes;
public:
~Group();
Group(std::vector<Polygon> polygons);
void show();
void tryChangingAllX();
};
#endif
Thanks!
The function
std::vector<Point> points();
returns by value, so when you call it, you get a copy of the member. You need to change it to
std::vector<Point>& points();
After you've done this
std::vector<Point> points = _ring.points();
also makes a copy of the returned value. To refer to the actual member in _ring, change to:
std::vector<Point>& points = _ring.points();
That should do it.
Note that you should pass std::vector by const reference to prevent an un-necessary copy:
Polygon(const std::vector<Point>& points);
and consider making methods that don't modify the class const:
int x() const;
This is exactly your problem - you're getting a copy of your points rather than working on a reference to the original points themselves.
polygon.cpp:
return points by reference not value:
std::vector<Point>& Polygon::points(){return _points;} // note the '&' in the return
group.cpp:
obtain a reference to the points, not a copy
std::vector<Point>& points = _ring.points(); // note the '&' in what you're getting
Answers posted by Luchian and lori are technically correct. But there are design considerations that I want to point out.
Returning a reference will allow anyone to modify private parts of Polygon object. By design you only want Group class to do this. Consider making Group a friend of Polygon. Group then will have access to private bits of Polygon. This will ensure a tighter encapsulation overall.
In polygon.h
friend class Group;
In group.cpp
void Group::tryChangingAllX()
{
for(std::vector<Point>::size_type i = 0; i != _ring._points.size(); i++)
{
_ring._points[i].x(15);
}
}