Error: reference to non-static member function - c++

I keep getting a compiler error at 6 points in my code that claim that a "reference to non-static member function must be called" in my Executive.cpp file, I can't figure out what the issue is but I believe it might be some sort of syntax error either in my Executive class or my ShapeContainer class. The ShapeContainer class just holds an array of various shapes from a Shape Interface that includes circles, triangles, and rectangles. Everything is read in from a file and the goal is to store the shapes from the file into the ShapeContainer class and then print certain areas the file says to do so.
Part of my Executive class and where the errors are:
//Executive.h
//...
class Executive
{
private:
int m_size;
int check;
ShapeContainer Shapes(int size);
ifstream inFile;
string FileName;
public:
Executive(string FileName);
void run();
};
//...
//Executive.cpp
//...
inFile.open(FileName);
int number;
inFile >> number;
while(check != 1)
{
string command = "";
int index = 0;
string shape = "";
double value1 = 0;
double value2 = 0;
inFile >> command >> index >> shape >> value1 >> value2;
if(command == "ADD")
{
if(shape == "CIRC")
{
Circle myCirc(value1);
try
{
Shapes.add(myCirc, index);//ERROR 1
}
catch(std::runtime_error& rte)
{
cout << rte.what() << "\n";
}
}
else if(shape == "TRI")
{
Triangle myTri(value1, value2);
try
{
Shapes.add(myTri(value1, value2), index);//ERROR 2
}
catch(std::runtime_error& rte)
{
cout << rte.what() << "\n";
}
}
else if(shape == "REC")
{
Rectangle myRect(value1, value2);
try
{
Shapes.add(myRect(value1, value2), index);//ERROR 3
}
catch(std::runtime_error& rte)
{
cout << rte.what() << "\n";
}
}
}
else if(command == "DELETE")
{
try
{
Shapes.remove(index);//ERROR 4
}
catch(std::runtime_error& rte)
{
cout << rte.what() << "\n";
}
}
else if(command == "PRINT")
{
cout << "Shape at index " << index << ": ";
try
{
cout << Shapes.shapeName(index) << " area = ";//ERROR 5
}
catch(std::runtime_error& rte)
{
cout << rte.what() << "\n";
}
try
{
cout << Shapes.area(index);//ERROR 6
}
catch(std::runtime_error& rte)
{
cout << rte.what() << "\n";
}
}
else if(command == "EXIT")
{
cout << "Exiting...\n";
check = 1;
}
}
inFile.close();
//...
Here is my ShapeContainer header file:
//ShapeContainer.h
#ifndef SHAPECONTAINER_H
#define SHAPECONTAINER_H
#include "Shape.h"
#include <stdexcept>
class ShapeContainer
{
public:
ShapeContainer(int size); //initialize pointers in m_arrayOfShapes to nullptr
~ShapeContainer();
double area(int index) const; //throws a std::runtime_error if index is invalid, meaning out of range OR index has nullptr
std::string shapeName(int index) const; //throws a std::runtime_error if index is invalid, meaning out of range OR index has nullptr
void add(Shape* shapePtr, int index); //throws a std::runtime_error if index is invalid OR if shapePtr is nullptr
void remove(int index); //throws a std::runtime_error if the index is invalid OR there is no object to delete
private:
Shape** m_arrayOfShapes;
int m_size;
};
#endif
And here is my Shape interface with an example of one of my shapes:
//Shape.h
#ifndef SHAPE_H
#define SHAPE_H
#include <string>
class Shape
{
public:
virtual double area() const = 0;
virtual std::string shapeName() const = 0;
virtual ~Shape() {}
};
#endif
//Circle.h
#ifndef CIRCLE_H
#define CIRCLE_H
#include "Shape.h"
class Circle:public Shape
{
public:
Circle(double radius);
double area()const;
std::string shapeName()const;
private:
double m_radius;
};
#endif
//Circle.cpp
#include "Circle.h"
Circle::Circle(double radius)
{
m_radius = radius;
}
double Circle::area()const
{
return((m_radius * m_radius) * 3.14);
}
std::string Circle::shapeName()const
{
return("Circle");
}
Here is the input file and my hopeful output:
//file.txt
5
ADD 0 CIR 5.5
ADD 1 TRI 2.5 6.6
PRINT 0
ADD 2 REC 10.5 20.25
PRINT 99
PRINT 2
EXIT
//output
Shape at index 0: Circle area = 95.0331
Shape at index 99: Does not exist
Shape at index 2: Rectangle area = 212.625
Exiting...

Related

Is there a way to get the derived class to have the base class edit the protected varibales

So I am experiencing a problem within this class assignment, we are set to code a "Tic Tac Toe" styled game. I thought it would be a good approach to have 2 versions such as original with 3 across and then 4 across. So here is the base class with the problem functions
Here is the minimal that leaves nothing cut out
main.cpp
#include "tic_tac_toe.h"
#include "tic_tac_toe_3.h"
#include "tic_tac_toe_4.h"
int main()
{
std::vector <std::reference_wrapper<Tic_tac_toe>> games;
string playerOption{ "" };
bool isRunning{ true }, error{ true };
int position{ 0 }, playerInt{ 0 };
char option{ ' ' };
//main loop
while (isRunning)
{
cout << "Tic Tac Toe game 3 or 4: ";
cin >> playerInt;
if (playerInt == 3)
{
cout << "Executing tic tac toe 3";
Tic_tac_toe_3 game3;
games.push_back(game3);
}
else if (playerInt == 4)
{
cout << "Executing tic tac toe 4";
tic_tac_toe_4 game4;
games.push_back(game4);
}
//allows for constant looping to get user to input X or O. So program wont blow up
while (error)
{
cout << "Player 1, X or O: ";
cin >> playerOption;
try
{
games[games.size() - 1].get().start_game(playerOption); //the .get gets the stored reference
error = false;
cout << "\n"; //to add a break in the text
}
catch (Error e)
{
cout << e.get_message();
}
}
try
{
cin >> games[games.size() - 1].get(); //FAIL POINT IMO
cout << games[games.size() - 1].get();
}
catch(Error e)
{
cout << e.get_message();
}
}
return 0;
}
tic_tac_toe.h
#include vector
using std::string;
class Tic_tac_toe
{
public:
Tic_tac_toe(int size) : pegs(size* size, " ") { } //multiply 3 or 4 by itself for 9 or 16
void start_game(std::string first_player);
void mark_board(int position);
friend std::ostream& operator<<(std::ostream& out, const Tic_tac_toe& t);
friend std::istream& operator>>(std::istream& in, Tic_tac_toe& b);
string get_player() const { return player; }
string get_winner() const { return winner; }
protected:
std::vector<string> pegs; //initializes a vector of x elements with each being a space.
private: //most logic goes within the private functions
void set_next_player();
string player;
}
tic_tac_toe.cpp
{
void Tic_tac_toe::start_game(std::string first_player)
{
if (first_player == "X" || first_player == "O")
{
player = first_player;
clearBoard();
}
else { throw Error("Player must be X or O\n"); }
}
void Tic_tac_toe::mark_board(int position)
{
if (position < 1 || position > 9)
{
throw Error("Position must be 1 to 9.\n");
}
else if (player == "")
{
throw Error("Must start game first.\n");
}
else
{
pegs[(position - 1)] = player; //minus one for the index
set_next_player();
}
}
std::ostream& operator<<(std::ostream& out, const Tic_tac_toe& b)
{
std::cout << "\n"; //formatting purposes
for (std::size_t i = 0; i < 9; i += 3) // += 3 for new row
{
out << b.pegs[i] + " | " + b.pegs[i + 1] + " | " + b.pegs[i + 2] + "\n";
}
return out;
}
std::istream& operator>>(std::istream& in, Tic_tac_toe& b)
{
std::cout << "Pegs size" << b.pegs.size();
int pos{ 0 };
std::cout << "Player " << b.get_player() << " enter a position: ";
in >> pos;
b.mark_board(pos);
return in;
}
}
tic_tac_toe_4 //4 and 3 are exactly same atm
class Tic_tac_toe_4 : public Tic_tac_toe
{
public:
tic_tac_toe_4() : Tic_tac_toe(4) { std::cout << "Passing to constructor"; }
}
Your program has undefined behavior, because you are pushing references to local variables such as
Tic_tac_toe_3 game3;
into games. When these variables leave their scope, the references in games become invalid and trying to use them later will have undefined behavior.
If you want a container that owns the Tic_tac_toe objects, then use
std::vector<std::unique_ptr<Tic_tac_toe>>
as type instead and create the objects with std::make_unique. Then the objects will live until the vector elements owning them are destroyed.

Program not running on some IDE's, issue with classes

Can someone help me find the issue in my code here?
I keep getting an error that just says program terminated. It runs on certain ide's but not others, and it hurts because I felt like I was starting to grasp the concepts of OOP, but guess not. The main idea of the program is to read the shape data into a pointer array and then display all of the information about the shapes.
#include <iostream>
#include <fstream>
#include <iomanip>
using namespace std;
// Global constant for array size.
const int SIZE = 99;
// Base Class
class Shape
{
protected:
char type;
int serNo;
int dim1;
int dim2;
public:
// Default constructor
Shape()
{
type = ' ';
serNo = 0;
dim1 = 0;
dim2 = 0;
}
// Constructor #1
Shape(char t, int s, int d1, int d2)
{
type = t;
serNo = s;
dim1 = d1;
dim2 = d2;
}
// Get type
char getType()
{
return type;
}
// Get serial number
int getSerNo()
{
return serNo;
}
// Get dimension1
int getDim1()
{
return dim1;
}
// Get dimension2
int getDim2()
{
return dim2;
}
// Destructor
~Shape()
{}
};
// Circle Class (Derived from Shape)
class Circle : public Shape
{
public:
Circle(char t, int s, int d1, int d2) : Shape(t, s, d1, d2)
{}
};
// Spray Class (Derived from Circle)
class Spray : public Circle
{
public:
// Constructor
Spray(char t, int s, int d1, int d2) : Circle(t, s, d1, d2)
{}
};
// Rectangle Class (Derived from Shape)
class Rectangle : public Shape
{
public:
// Constructor
Rectangle(char t, int s, int d1, int d2) : Shape(t, s, d1, d2)
{}
};
// Square Class (Derived from Rectangle)
class Square : public Rectangle
{
public:
// Constructor
Square(char t, int s, int d1, int d2) : Rectangle(t, s, d1, d2)
{}
};
class mgrShape : public Shape
{
protected:
int recordCount;
Shape * shapeArr[SIZE] = {nullptr}; // Manager owns the main data
//structure
public:
// Constructor.
mgrShape()
{
populateShapeData();
}
// Populate the shapeArr from file.
void populateShapeData()
{
fstream inputFile;
string fileName = "shaperecords.txt";
inputFile.open(fileName);
while(inputFile >> type >> serNo >> dim1 >> dim2)
{
if (type == 'C')
shapeArr[recordCount] = new Circle(type, serNo, dim1, dim2);
else if (type == 'R')
shapeArr[recordCount] = new Rectangle(type, serNo, dim1, dim2);
else if (type == 'S')
shapeArr[recordCount] = new Spray(type, serNo, dim1, dim2);
else if (type == 'Q')
shapeArr[recordCount] = new Square(type, serNo, dim1, dim2);
recordCount++;
}
inputFile.close();
}
//Display all of the shapes.
void displayAll()
{
for (int i = 0; i < recordCount; i++)
{
if (shapeArr[i]->getType() == 'C')
{
cout << "Circle Found!" << endl;
cout << shapeArr[i]->getType() << endl;
cout << shapeArr[i]->getSerNo() << endl;
cout << shapeArr[i]->getDim1() << endl;
cout << shapeArr[i]->getDim2() << endl;
}
else if (shapeArr[i]->getType() == 'R')
{
cout << "Rectangle Found!" << endl;
cout << shapeArr[i]->getType() << endl;
cout << shapeArr[i]->getSerNo() << endl;
cout << shapeArr[i]->getDim1() << endl;
cout << shapeArr[i]->getDim2() << endl;
}
else if (shapeArr[i]->getType() == 'S')
{
cout << "\nSpray Found!" << endl;
cout << shapeArr[i]->getType() << endl;
cout << shapeArr[i]->getSerNo() << endl;
cout << shapeArr[i]->getDim1() << endl;
cout << shapeArr[i]->getDim2() << endl;
}
else if (shapeArr[i]->getType() == 'Q')
{
cout << "Square Found!" << endl;
cout << shapeArr[i]->getType() << endl;
cout << shapeArr[i]->getSerNo() << endl;
cout << shapeArr[i]->getDim1() << endl;
cout << shapeArr[i]->getDim2() << endl;
}
}
}
// Clear the dynamically allocated memory from shapeArr.
~mgrShape()
{
for (int i = 0; i < recordCount; i++)
delete shapeArr[i];
}
};
int main()
{
mgrShape ms;
ms.displayAll();
return 0;
}
//And here's the input file's contents
//C 1001 30 -1
//R 1002 14 10
//S 1003 30 20
//Q 1004 28 -1
//S 1005 30 75

0xC0000005: Access violation reading location 0xCDCDCDC1

I wrote the code that can generate random Geometry figures and display it in cmd in text form.
Here is my 3 files:
Geometry.h
#pragma once
#define _CRTDBG_MAP_ALLOC
#include <crtdbg.h>
#define DEBUG_NEW new(_NORMAL_BLOCK, __FILE__, __LINE__)
#define new DEBUG_NEW
#include <iostream>
#include <time.h>
#include <fstream>
#include <string>
#define PI 3.1415926535
using namespace std;
enum color { White, Red, Green, Blue, Yellow, Black };
enum _shape { line, rectangle, circle, picture }; //to roll shapes
void print_color(color c);
//--------------------------Point---------------------------
class Point {
private:
int m_xc, m_yc; //(x,y) coordinats
public:
Point(int x = 0, int y = 0) : m_xc(x), m_yc(y) {}
int x(void) const { return m_xc; };
int y(void) const { return m_yc; };
Point operator+(const Point& p) const
{
return Point(m_xc+p.m_xc, m_yc+p.m_yc);
}
Point& operator+=(const Point& p) //move point
{
m_xc += p.m_xc;
m_yc += p.m_yc;
return *this;
}
friend ostream& operator<<(ostream& os, const Point& p);
Point move(int x, int y){
m_xc += x;
m_yc += y;
return *this;
}
};
//------------------------Shape-----------------------------
class Shape {
protected:
Point m_org;
color m_color;
_shape m_shape;
public:
Shape(const Point& p1 = 0, color c = White, _shape sh = line) : m_org(p1), m_color(c), m_shape(sh){};
virtual ~Shape() = 0 {};
virtual void move(const Point& p) = 0;
virtual void draw(char tabs) const = 0;
virtual void Who_am_I() const = 0;
virtual double Area() const { return 0; };
virtual void Save2File(ofstream &myfile) const = 0;
};
//------------------------Line---------------------------------
class Line : public Shape {
protected:
Point m_end; // line end
public:
Line(const Point& p1, const Point& p2, color c) : Shape(p1, c, line), m_end(p2) {}
void move(const Point& p)
{
m_org += p;
m_end += p;
}
void draw(char tabs) const;
void Who_am_I() const {
print_color(m_color);
cout << "Line";
}
double length() const;
double Area() const { return 0; };
void Save2File(ofstream &myfile) const;
};
//----------------------Rectangle-------------------------------
class Rectangle : public Shape {
protected:
int width;
int height;
public:
Rectangle(const Point& p1, color c = White, int w = 0, int h = 0) : Shape(p1, c, rectangle), width(w), height(h) {}
void move(const Point& p)
{
m_org += p;
}
void draw(char tabs) const;
void Who_am_I() const {
print_color(m_color);
cout << "Rectangle";
}
double Area() const { return width*height; };
void Save2File(ofstream &myfile) const;
};
//----------------------Circle---------------------------
class Circle : public Shape {
protected:
int radius;
public:
Circle(const Point& p1, color c = White, int r = 0) : Shape(p1, c, circle), radius(r) {};
void move(const Point& p)
{
m_org += p;
}
void draw(char tabs) const;
void Who_am_I() const {
print_color(m_color);
cout << "Circle";
}
double Area() const { return PI*(double)radius*(double)radius; };
void Save2File(ofstream &myfile) const;
};
//--------------------------Picture-------------------------
class Picture : public Shape {
private:
Picture(const Picture&); //CCtor is not accessible from main
protected:
Shape** m_shapes; //array of pointers to shapes
int m_count; //number of shapes
static unsigned idx; //number of pictures created for debug
public:
Picture(const Point& p1 = 0, color c = White) : Shape(p1, c, picture), m_count(0){ idx++; }
~Picture();
void insert_shape(Shape* sh);
void draw(char tabs) const;
void move(const Point& p){ m_org += p; };
void Who_am_I() const {
print_color(m_color);
cout << "Picture";
}
void Save2File(ofstream &myfile) const;
int get_count(void){ return m_count; }
double Area() const;
unsigned GetAmPic(void) { return idx; }
};
Geometry.cpp
#define _CRTDBG_MAP_ALLOC
#include <crtdbg.h>
#define DEBUG_NEW new(_NORMAL_BLOCK, __FILE__, __LINE__)
#define new DEBUG_NEW
#include "geometry.h"
using namespace std;
unsigned Picture::idx = 0;
ostream& operator<<(ostream& os, const Point& p)
{
os << '(' << p.x() << ',' << p.y() << ')';
return os;
}
void print_color(color c) {
string color_print[6] = { "White ", "Red ", "Green ", "Blue ", "Yellow ", "Black " };
cout << color_print[(int)c];
}
//------------------Line methods--------------------
void Line::draw(char tabs) const
{
cout << string(tabs, '\t');
Who_am_I();
cout << " from " << m_org << " to " << m_end << endl;
}
double Line::length() const
{
return sqrt((double)((m_org.x()-m_end.x())*(m_org.x()-m_end.x()) + (m_org.y()-m_end.y())*(m_org.y()-m_end.y())));
}
void Line::Save2File(ofstream& myfile) const {// save to file
myfile << 'L' << " " << m_color << " " << m_org.x() << " " << m_org.y() << " "
<< m_end.x() << " " << m_end.y() << endl;
}
//------------------Rectangle methods----------------
void Rectangle::draw(char tabs) const
{
cout << string(tabs, '\t');
Point temp1 = m_org;
Point temp2 = m_org;
Line l1(temp1, temp2.move(width, 0), m_color);
temp1 = temp2;
Line l2(temp2, temp1.move(0, height), m_color);
temp2 = temp1;
Line l3(temp1, temp2.move(-width, 0), m_color);
temp1 = temp2;
Line l4(temp2, temp1.move(0, -height), m_color);
Who_am_I(); cout << endl;
cout << string(tabs, '\t'); l1.draw(1);
cout << string(tabs, '\t'); l2.draw(1);
cout << string(tabs, '\t'); l3.draw(1);
cout << string(tabs, '\t'); l4.draw(1);
}
void Rectangle::Save2File(ofstream& myfile) const {// save to file
myfile << 'R' << " " << m_color << " " << m_org.x() << " " << m_org.y() << " " << width
<< " " << height << endl;
}
//----------------------Circle methods---------------------------
void Circle::draw(char tabs) const
{
cout << string(tabs, '\t');
Who_am_I();
cout << " Center in " << m_org << " Radius is " << radius << endl;
}
void Circle::Save2File(ofstream& myfile) const {// save to file
myfile << 'C' << " " << m_color << " " << m_org.x() << " " << m_org.y() << " "
<< radius << endl;
}
//----------------------Picture methods--------------------------
void Picture::insert_shape(Shape* s) // insert a new shape to picture
{
if (m_count == 0) {//new picture creating
m_shapes = new Shape*[1];
if (!m_shapes)
cout << "Can't allocate memory!";
}
if (m_count > 0){
Shape** temp = new Shape*[m_count];
memcpy(temp, m_shapes, sizeof(Shape*)*m_count); //save to temp
delete m_shapes; //delete old array
m_shapes = new Shape*[m_count + 1]; //add 1 more place
if (!m_shapes)
cout << "Can't allocate memory!";
memcpy(m_shapes, temp, sizeof(Shape*)*m_count); //return to array
delete temp;
}
m_shapes[m_count] = s; // insert the new shape into the last slot in the array
m_shapes[m_count]->move(m_org); //adjusts the location of the shape
m_count++; // increment the number of shapes in picture
}
void Picture::draw(char tabs) const
{
cout << string(tabs, '\t');
cout << "------------------ ";
Who_am_I();
cout << " ----------------------" << endl;
for (unsigned i = 0; i < m_count; i++)
{
m_shapes[i]->draw(tabs + 1); // draw each shape
}
cout << string(tabs, '\t');
cout << "------------------ End ";
Who_am_I();
cout << " ------------------ " << endl;
}
double Picture::Area() const //sum of areas of all shapes in the picture
{
double area = 0;
for (int i = 0; i < m_count; i++)
{
area += m_shapes[i]->Area();
}
return area;
}
Picture::~Picture()
{
for (int i = 0; i < m_count; i++){
if (m_shapes[i])
delete m_shapes[i];
}
Who_am_I(); cout << " deleting..." << endl;
// sometimes (every 5-10 runs) error here. can't reproduce and debug
if (m_shapes)
delete m_shapes;
// seems like program try to delete already freed memory
}
void Picture::Save2File(ofstream& myfile) const // save to file
{
myfile << 'P' << " " << m_color << " " << m_org.x() << " " << m_org.y() << endl;
for (int i = 0; i < m_count; i++)
m_shapes[i]->Save2File(myfile);
myfile << 'E' << endl; // end of a picture
}
drawing_app.cpp
#define _CRTDBG_MAP_ALLOC
#include <crtdbg.h>
#define DEBUG_NEW new(_NORMAL_BLOCK, __FILE__, __LINE__)
#define new DEBUG_NEW
#include "geometry.h"
#include <iostream>
#define MAX_PICS_IN_PIC 3
#define MAX_SHAPES 5
using namespace std;
void randomizer(Picture*, int); //recursive function
Picture* Load(istream&);
Point GenP(void);
color GenC(void);
int GenLen(void);
int main(void)
{
srand((unsigned int)time(NULL));
Picture *main_pic = new Picture(Point(0, 0), GenC());
ofstream myfile_write("myfile.txt", ios::out);
if (!myfile_write.is_open())
cout << "Can't open file!" << endl;
randomizer(main_pic, MAX_PICS_IN_PIC); //recursive function
main_pic->Save2File(myfile_write); //save picture to file
myfile_write.close();
cout << " Created Picture:" << endl << endl;
main_pic->draw(0); //draw the main picture
cout << "Created: " << main_pic->GetAmPic() << " pictures." << endl; // for debugging
delete[] main_pic;
ifstream myfile_read("myfile.txt", ios::in);
if (!myfile_read.is_open())
cout << "Can't open file!" << endl;
Picture* buff_pic = Load(myfile_read); //load the picture from the file
cout << endl << endl << " Loaded Picture:" << endl << endl;
buff_pic->draw(0); //display loaded picture
myfile_read.close();
delete[] buff_pic;
cout << "\nLeaks: " << _CrtDumpMemoryLeaks() << endl;
return 0;
}
void randomizer(Picture* pic, int count) {
for (int i = 0; i < MAX_SHAPES; i++){
Point p1 = GenP(); //m_org of the shape
color c = GenC(); //roll random color
_shape shape;
shape = (_shape)(rand() % 4); //roll random shape
if (shape == line){
Point p2 = GenP();
Line* _line = new Line(p1, p2, c);
pic->insert_shape(_line);
}
if (shape == rectangle){
Rectangle* _rect = new Rectangle(p1, c, GenLen(), GenLen());
pic->insert_shape(_rect);
}
if (shape == circle){
Circle* _circ = new Circle(p1, c, GenLen());
pic->insert_shape(_circ);
}
if (shape == picture){
if (count > 0){
Picture* inner_pic = new Picture(p1, c);
count--;
randomizer(inner_pic, count);
pic->insert_shape(inner_pic);
}
else return;
}
}
}
Picture* Load(istream& myfile) {
int m_color, m_org_x, m_org_y;
char m_shape;
myfile >> m_shape >> m_color >> m_org_x >> m_org_y; //read first line
Picture* pic = new Picture(Point(m_org_x, m_org_y), (color)m_color); //create the main picture
myfile >> m_shape; //read next line for shape
while (m_shape != 'E')
{
if (m_shape == 'L'){
int m_end_x, m_end_y;
myfile >> m_color >> m_org_x >> m_org_y >> m_end_x >> m_end_y;
Line* _line = new Line(Point(m_org_x, m_org_y), Point(m_end_x, m_end_y), (color)m_color);
pic->insert_shape(_line);
}
if (m_shape == 'C'){
int radius;
myfile >> m_color >> m_org_x >> m_org_y >> radius;
Circle* Circel = new Circle(Point(m_org_x, m_org_y), (color)m_color, radius);
pic->insert_shape(Circel);
}
if (m_shape == 'R') {
int m_width, m_height;
myfile >> m_color >> m_org_x >> m_org_y >> m_width >> m_height;
Rectangle* Rect = new Rectangle(Point(m_org_x, m_org_y), (color)m_color,
m_width, m_height);
pic->insert_shape(Rect);
}
if (m_shape == 'P') {
myfile.seekg(-1, ios::cur);
Picture* inner_pic = Load(myfile);
pic->insert_shape(inner_pic);
}
myfile >> m_shape;
}
return pic;
}
Point GenP(){ //roll random point x = 0 to 30, y = 0 to 30
Point p(rand() % 31, rand() % 31);
return p;
}
color GenC(){ //generate random color
return (color)(rand() % 6);
}
int GenLen(){ // generate random length from 1 to 50
return rand() % 50 + 1;
}
Every 5-10 runs I got strange error:
Unhandled exception at 0x5214A9E8 (msvcr120d.dll) in Geometry.exe: 0xC0000005: Access violation reading location 0xCDCDCDC1.
Referring me to Destructor of Picture class. I can't reproduce this error and can't find the source of this error. Do you have any ideas how I can debug it?
The obvious error is that it is entirely (and easily) possible to attempt to delete an uninitialized m_shapes pointer in the Picture destructor.
The outline of your code is this:
class Picture : public Shape {
private:
Picture(const Picture&); //CCtor is not accessible from main
protected:
Shape** m_shapes; //array of pointers to shapes
int m_count; //number of shapes
static unsigned idx; //number of pictures created for debug
public:
Picture(const Point& p1 = 0, color c = White) : Shape(p1, c, picture), m_count(0){ idx++; }
//...
~Picture();
};
In the ~Picture() function, you do the following:
Picture::~Picture()
{
for (int i = 0; i < m_count; i++){
if (m_shapes[i])
delete m_shapes[i];
}
if (m_shapes) // This may not have been initialized!!
delete m_shapes;
}
In the Picture() constructor, you failed to initialize m_shapes, thus a simple one line program would be able to invoke the undefined behavior of calling delete on an uninitialized pointer.
Example:
int main()
{
Picture p(Picture(Point(0, 0), GenC()));
} // The `p` destructor will invoke undefined behavior.
Therefore the immediate fix is to go back and make sure m_shapes is initialized to (at least) a nullptr on construction of Picture.
However the ultimate fix is to start to use std::vector and other containers, in addition to using smart pointers such as std::shared_ptr<Shape> and/or std::unique_ptr<Shape>. When you do this, functions such as Picture::insert_shape become either obsolete, or are simple one-line functions issuing a call to (for example) std::vector<Shape*>::push_back().
For example (using a vector of raw pointers)
#include <vector>
class Picture
{
//...
std::vector<Shape *> m_shapes;
void insert_shape(Shape* s);
//...
};
void Picture::insert_shape(Shape* s)
{
m_shapes.push_back(s);
}
If you want to debug the crash in C++ code, let me show you how to use and inspect dumps:
Use adplus.exe (get it from Microsoft) and run your app in process monitor mode
Download WinDBG (also from Microsoft)
Use the following command to create a dump in monitor mode of your process
ADPlus -Crash -pmn Geometry.exe -o C:\CrashDumps
Open the crash dump in WinDBG
Learn the power of WinDBG
A note: You might need symbols (.pdb) files to be created/loaded in your dump inspection
The error is in this line.
Picture *main_pic = new Picture(Point(0, 0), GenC());
You're not giving the size to your Picture pointer and you're deleting it like an array, You must assign a size to your pointer then you also can delete is like this.
delete [] main_pic;

"Ambiguous Overload" issues in loop, and malfunctioning cin

I'm building a menu creation class with a member function that should display the menu, get a selection from the user, test if it's a valid menu item, and return the number of the item. For some reason, the compiler is giving me an "ambiguous overload for operator '>>'" error on a simple cin statement in the run() member function below. When run, the function catches invalid input properly, but then considers all input after that invalid. If the first input is correct, the program terminates outright. Here's my code:
#include <iostream>
#include <vector>
using namespace std;
class NumericalMenu {
private:
string prompt;
vector<string> options;
string canceltext;
string errortext;
bool repeatprompt;
int sel;
public:
NumericalMenu() {
prompt = "Choose an option:";
canceltext = "Cancel";
errortext = "Error!";
repeatprompt = true;
sel = 0;
};
void setPrompt(string text) {
prompt = text;
};
int size() const {
int size = options.size() + 1;
return size;
};
int addOption(string text) {
options.push_back(text);
int position = options.size() - 1;
return position;
};
void setCancelText(string text) {
canceltext = text;
};
void setRepeatPromptOnError(bool repeat) {
repeatprompt = repeat;
};
void setErrorText(string text) {
errortext = text;
};
int run() const{
cout << prompt << "\n\n";
for (unsigned i=0; i<options.size(); i++) {
cout << i+1 << " - " << options[i] << "\n";
}
int errorpos = this->size();
cout << errorpos << " - " << canceltext << "\n\n";
cin.clear();
cin.ignore();
cin >> sel;
if(cin.fail() || sel<=0 || sel>errorpos) {
cout << "\n" << errortext << "\n\n";
if(repeatprompt == true) {
cin.clear();
cin.ignore();
this->run();
}
}
if (sel == errorpos) {
return -1;
} else {
return sel;
}
};
};
int main() {
NumericalMenu menu;
menu.setPrompt("Choose an option:");
menu.addOption("Enter new values");
menu.addOption("Help");
menu.addOption("Save");
menu.setCancelText("Exit");
menu.run();
}
Edit: Got it! Thanks everyone. The working header:
#include <iostream>
#include <vector>
#include <string>
using namespace std;
class NumericalMenu {
private:
string prompt;
vector<string> options;
string canceltext;
string errortext;
bool repeatprompt;
public:
NumericalMenu() {
prompt = "Choose an option:";
canceltext = "Cancel";
errortext = "Error!";
repeatprompt = true;
};
void setPrompt(string text) {
prompt = text;
};
int size() const{
int size = options.size() + 1;
return size;
};
int addOption(string text) {
options.push_back(text);
int position = options.size() - 1;
return position;
};
void setCancelText(string text) {
canceltext = text;
};
void setRepeatPromptOnError(bool repeat) {
repeatprompt = repeat;
};
void setErrorText(string text) {
errortext = text;
};
int run() const{
cout << prompt << "\n\n";
for (unsigned i=0; i<options.size(); i++) {
cout << i+1 << " - " << options[i] << "\n";
}
int errorpos = this->size();
cout << errorpos << " - " << canceltext << "\n\n";
int sel;
cin.clear();
cin >> sel;
if(cin.fail() || sel<=0 || sel>errorpos) {
cout << "\n" << errortext << "\n\n";
if(repeatprompt == true) {
cin.clear();
cin.ignore(1000, '\n');
int sele = this->run();
return sele;
}
}
if (sel == this->size()) {
return -1;
}
else {
return sel;
}
};
};
You declared your run() function as const and preventing modifications to member variables is being enforced by the compiler.
class NumericalMenu {
private:
int sel;
...
int run() const {
cin >> sel; // Not allowed
If you need to modify member variables, remove the const in your inline run() function definition.
Furthermore as a good practice try to include all the headers you directly use in your code (i.e. <string>).

Obj Loader not displaying properly

so this is an obj loader in c++ using opengl
it seem displays the cube i input as a flat it seems to position them correctly but all objects i have tried come out as a plane (see pictures)
https://docs.google.com/file/d/0B8AdFl9H3IJVRG9FbFo1UnpWaUE/edit?usp=sharing
i have tried other 3d objects and they all seem to come out as this plane (may difer in size)
what i have tried
going over other obj loaders online
slowly running through the debug
checking the vectors load properly
checking to see if the reading in is corect
List item
typedef.h
#pragma
typedef struct {
float x,y,z;
} points;
typedef struct {
float vn[3]; // store the ve3rtex normals
} normal;
typedef struct {
float vt[3]; // store the texture coordinates
} coordinate;
typedef struct {
int shaders;
points p[3];
normal norm[3];
coordinate coord[3];
} face;
loader.h
#pragma once
#include <string>
#include <vector>
#include <fstream>
#include <GL/freeglut.h>
#include<iostream> // this is just for testing, you can remove this with all the cout's
#include "typedef.h"
class Loader
{
public:
Loader(std::string input);
~Loader(void);
void draw(); // this function takes the obj file and draws it
private:
std::ifstream m_inFile;
// the list of vectors that i will be using
std::vector<points> m_points;
std::vector<normal> m_normals;
std::vector<coordinate> m_coords;
std::vector<face> m_faces;
void process(std::string input);
void inputPoints(points temp);
void inputNormals(normal temp);
void inputCoordinates(coordinate temp);
void createFaces(face temp);
};
loader.cpp
#include "Loader.h"
Loader::Loader(std::string input)
{
process(input);
}
Loader::~Loader(void)
{
}
void Loader::process(std::string input)
{
std::string identifier; //used to identify where the input should go
points temppoint;
normal tempnormal;
coordinate tempcoord;
face tempface;
std::string read; // used to read the curent line
int readNum; // this is the number that has just been read in
char skip; // a char to skip thr /
int i;
int count= 1;
m_inFile.open(input);
/* // check to see if it read
if(!m_inFile)
std::cout << "did not read";
else
std::cout << "file read";
*/
//creation of the reading loop
//while(!m_inFile.eof())
m_inFile >> identifier;
do {
// check to see what the opening is
if (identifier =="#")
{
getline(m_inFile,read); // use this to read the whole line
}
else if(identifier == "v")
{
m_inFile >> temppoint.x >> temppoint.y >> temppoint.z;
inputPoints(temppoint);
}
else if(identifier == "vn")
{
m_inFile >> tempnormal.vn[0] >> tempnormal.vn[1] >> tempnormal.vn[2];
inputNormals(tempnormal);
}
else if (identifier == "vt")
{
m_inFile >> tempcoord.vt[0] >> tempcoord.vt[1] >> tempcoord.vt[2];
inputCoordinates(tempcoord);
}
else if(identifier == "f")
{
for( i =0; i < 3; i++)
{
//std::cout << "loops: " << count << std::endl;
count++;
//if(read == "Material.001")
// std::cout << std::endl;
//std::cout << "Iteration: " << i << std::endl;
m_inFile >> readNum;
if(readNum == 0)
break;
readNum--;
tempface.p[i].x = m_points[readNum].x;
tempface.p[i].y = m_points[readNum].x;
tempface.p[i].z = m_points[readNum].z;
m_inFile >> skip >> readNum;
readNum--;
tempface.coord[i].vt[0] = m_coords[readNum].vt[0];
tempface.coord[i].vt[1] = m_coords[readNum].vt[1];
tempface.coord[i].vt[2] = m_coords[readNum].vt[2];
m_inFile >> skip >> readNum;
readNum--;
tempface.norm[i].vn[0] = m_normals[readNum].vn[0];
tempface.norm[i].vn[1] = m_normals[readNum].vn[1];
tempface.norm[i].vn[2] = m_normals[readNum].vn[2];
}
createFaces(tempface);
}
else
{
getline(m_inFile,read);
std::cout << "Not Processed " << identifier << " " << read <<std::endl;
}
m_inFile >> identifier;
} while (!m_inFile.eof());
}
void Loader::inputPoints(points temp)
{
m_points.push_back(temp);
}
void Loader::inputNormals(normal temp)
{
m_normals.push_back(temp);
}
void Loader::inputCoordinates(coordinate temp)
{
m_coords.push_back(temp);
}
void Loader::createFaces(face temp)
{
m_faces.push_back(temp);
}
void Loader::draw()
{
int i;
int j;
glBegin(GL_TRIANGLES);
for (i=0; i < m_faces.size();i++)
{
//std::cout<<"glBegin" <<std::endl;
for(j = 0 ; j < 3; j++)
{
//std::cout << "Vn1: "<< m_faces[i].norm[j].vn[0] << "Vn2: " << m_faces[i].norm[j].vn[1] <<"Vn3: "<< m_faces[i].norm[j].vn[2] << std::endl;
//std::cout << "X: " << m_faces[i].p[j].x << "Y: " << m_faces[i].p[j].y << "Z: " << m_faces[i].p[j].z << std::endl;
//glNormal3f(m_faces[i].norm[j].vn[0],m_faces[i].norm[j].vn[1],m_faces[i].norm[j].vn[2]);
glVertex3f(m_faces[i].p[j].x,m_faces[i].p[j].y,m_faces[i].p[j].z);
}
//glEnd();
//std::cout << "glEnd()" << std::endl <<std::endl;
}
glEnd();
}
inside main i call a function called banner
void Banner()
{
glTranslatef(15000.0,11000.0,25000.0);
glScalef(100,100,100);
lod.draw();
}
which is badly created as a global