Inheritance with segmentation fault - c++

I'm working on inheritance right now. I have a base class called Shape, and few others as sub class. There is no compilation error. But after when i enter all the coordinates, segmentation error pops out. Inside the driver class, option when when i tried using this d[count].toString();
Shape.h
class Shape
{
protected:
string name;
bool containsWarpSpace;
public:
Shape();
Shape(string, bool);
string toString();
virtual double computeArea();
void setName (string);
// some other codes here
};
Square.h
class Square : public Shape
{
protected:
int *x;
int *y;
int area;
int vertices;
public:
double computeArea();
void setSquare(string, string, int*, int*);
string toString();
};
Square.cpp
void Square::setSquare(string name, string type, int* a, int* b)
{
setName(name);
setContainsWarpSpace (type);
vertices = 4;
x = new int[vertices];
y = new int[vertices];
for (int i = 0; i < vertices; i++)
{
x[i] = a[i];
y[i] = b[i];
}
}
string Square::toString()
{
ostringstream convert;
string s;
string type;
for (int i = 0; i < vertices; i++)
{
convert << "point " << i + 1
<< " ( "
<< x[i] << " , " << y[i]
<< " ) "<< endl;
}
s = convert.str();
return s;
}
Driver class with int main()
class Driver
{
public:
Driver();
Shape *d[];
Square *s;
int count;
int noSquare;
int noRectangle;
int noCross;
void printDetails();
void printPlan();
void option1();
void option2();
void option3();
void option4();
string convertString(string);
};
Driver.cpp. This is the default constructor,
Driver :: Driver()
{
Shape d [MAX];
s = new Square [MAX];
count = 0;
int noSquare = 0;
int noRectangle = 0;
int noCross = 0;
}
Driver::option1()
{
if (shape.compare("square") == 0)
{
tempx = new int[4];
tempy = new int[4];
for (int i = 0; i < 4; i++)
{
int j = i + 1;
cout << "Please enter x-ordinate of pt " << j << ": ";
cin >>tempx[i];
cout << "Please enter y-ordinate of pt " << j << ": ";
cin >>tempy[i];
}
s[noSquare].setSquare(shape,type, tempx,tempy);
d[count] = &s[noSquare];
d[count].toString();
}
}
int main ()
{
option1();
}

Change the way you declared your shape in Driver class. In the header, declare it as :
Shape* d;
and in your CPP initialize it:
d = new Shape[MAX];
Also, since you are doing inheritance and arrays and pointers, you should manage your own destructors. Because if the chil object gets destroyed, it will take parent destructor. Therefore, your destructors should be:
virtual ~Shape();
And square:
virtual ~Square();
In them, delete the pointers:
delete x; // in case of square
delete y;
And when you have arrays:
delete [] d; // in case of driver class
Otherwise it will not free memory properly. That would probably fix your problems.

Related

Passing 2d Vector by Reference, Changes Not Persisting

So in my program, I'm using polymorphism, which could also explain some of the issues that I'm having.
This is my pure abstract class:
class Event {
public:
Event();
~Event();
virtual int returnType();
};
Then I have a room class that sets events to a particular room:
class Room {
private:
Event * e;
bool player = false;
bool bEvent = false;
public:
Room();
~Room();
Event * getEvent();
void setEvent(Event *);
bool getPlayer();
void setPlayer(bool);
bool getBoolEvent();
void setBoolEvent(bool);
};
And here are my function definitions:
Event * Room::getEvent() {
return e;
}
void Room::setEvent(Event * n) {
e = n;
}
bool Room::getPlayer() {
return player;
}
void Room::setPlayer(bool p) {
player = p;
}
bool Room::getBoolEvent() {
return bEvent;
}
void Room::setBoolEvent(bool b) {
bEvent = b;
}
Here is my bats class which is a derived class from event: The functions are the same, so here are the function definitions:
int Bats::returnType() {
return 1;
}
So in my program, I am using a 2d vector of Rooms, and then assigning events to these rooms via polymorphism. The problem is that I don't think the changes are persisting, at least with the polymorphism, even when passing by reference.
Here is the function where I am setting the bat event to a certain room in the 2d vector:
vector<vector<Room>> Game::setEvents(vector<vector<Room>> &grid) {
Bats b1;
Event * eb1 = &b1;
//Set player
int r1 = rand()%gridSize;
int r2 = rand()%gridSize;
grid[r1][r2].setPlayer(true);
//Set bats
grid[0][0].setBoolEvent(true);
grid[0][0].setEvent(eb1);
cout << "Function example: " << grid[0][0].getEvent()->returnType() << endl;
return grid;
}
As an output I get Function example: 1;
However, when we move into the main (in this case Game::play()) function, these changes don't hold.
void Game::play() {
srand(time(NULL));
//Create vector
vector<vector<Room>> grid;
//Fill vector
fillGrid(grid);
//Set player and events
grid = setEvents(grid);
for (int i = 0; i < gridSize; i++) {
for (int j = 0; j < gridSize; j++) {
if (grid[i][j].getBoolEvent() == true) {
cout << i << " " << j << endl;
cout << grid[i][j].getEvent()->returnType() << endl;
}
}
}
}
As an output I get 0 0 and then a seg fault.
Although the boolEvent is still true, for some reason I get a segmentation fault when trying to call returnType(), even though it worked in the setEvents() function. What am I doing wrong with polymorphism?

Run-Time Check Failure #2 - Stack around the variable 'c2d' was corrupted. with c++

I'm studying for an exam and this is on my practice test. The question is "Which type of error does the following code fragment cause?"
Why is there an error?
struct C2D {
double x, y;
};
class Polygon {
int point;
C2D arr[];
public:
Polygon(int point_, C2D arr_[]) {
point = point_;
memcpy(arr, arr_, sizeof(C2D) * point);
};
void print() const {
for (int i = 0; i < point; i++) {
cout << arr[i].x << " " << arr[i].y << endl;
}
};
};
int main() {
C2D c2d[3];
c2d[0].x = 1;
c2d[0].y = 2;
c2d[1].x = 3;
c2d[1].y = 4;
c2d[2].x = 5;
c2d[2].y = 6;
Polygon p1(3, c2d);
p1.print();
return 0;
}
You didn't specify number of elements for the member
C2D arr[];
so there are no memory allocated for that.
You should use std::vector to allocate elements dynamically.
#include <iostream>
#include <vector>
#include <cstring>
using std::cout;
using std::endl;
struct C2D {
double x, y;
};
class Polygon {
int point;
std::vector<C2D> arr;
public:
Polygon(int point_, C2D arr_[]) : arr(point_) { // allocate point_ elements for arr
point = point_;
memcpy(arr.data(), arr_, sizeof(C2D) * point); // copy data using data()
};
void print() const {
for (int i = 0; i < point; i++) {
cout << arr[i].x << " " << arr[i].y << endl;
}
};
};
int main() {
C2D c2d[3];
c2d[0].x = 1;
c2d[0].y = 2;
c2d[1].x = 3;
c2d[1].y = 4;
c2d[2].x = 5;
c2d[2].y = 6;
Polygon p1(3, c2d);
p1.print();
return 0;
}

C++ pointer syntax in class constructor leading to malloc error

Background
I am self-learning C++ from this course, and I am unsure whether I understand why exactly my syntax was wrong.
Problem
Please see the two versions of the PointArray constructor in geometry_test.cpp. The first one gives an error, while the second one comes from the solution manual. In my (probably flawed) understanding, the two versions should be equivalent. Where have I gone wrong? When am I referring to the member attributes points and size? and when am I referring to the input variables points and size?
Thank you for any clarifications or suggestions to references I should check out.
Related query
How might the error message suggest a solution?
Code
geometry_test.h
class Point {
private:
int x, y;
public:
Point(int create_x = 0, int create_y = 0) { x = create_x; y = create_y; };
int getX() const { return x; };
int getY() const { return y; };
void setX(const int new_x) { x = new_x; };
void setY(const int new_y) { y = new_y; };
};
class PointArray {
private:
Point *points;
int size;
void resize(int n);
public:
PointArray(const Point points[], const int size);
~PointArray() { delete[] points; };
};
geometry_test.cpp
#include "geometry.h"
#include <iostream>
using std::cout;
PointArray::PointArray(const Point points[], const int size) { // breaks
points = new Point[size];
this->size = size;
for (int i = 0; i < size; ++i) { this->points[i] = points[i]; }
}
/*
PointArray::PointArray(const Point ptsToCp[], const int toCpSz) { // works
points = new Point[toCpSz];
size = toCpSz;
for (int i = 0; i < toCpSz; ++i) { points[i] = ptsToCp[i]; }
}
*/
int main() {
Point p1(1, 0);
Point p2(2, 0);
Point p3(1, 1);
Point ptarray[3] = {p1, p2, p3};
PointArray pa(ptarray, 3);
cout << p1.getX() << ", " << p1.getY() << "\n";
cout << p2.getX() << ", " << p2.getY() << "\n";
cout << p3.getX() << ", " << p3.getY() << "\n";
return 0;
}
Error message
geometry_test(17467,0x11b51adc0) malloc: *** error for object 0x7ffee4705690: pointer being freed was not allocated
geometry_test(17467,0x11b51adc0) malloc: *** set a breakpoint in malloc_error_break to debug
Abort trap: 6

Why the number of grades is 0?

#include<iostream>
#include<string>
using namespace std;
class Student {
public:
const int codeStud;
int noGrades = 0;
int* grades = NULL;
Student(int code) :codeStud(code) {
}
Student(int code, int* grades, int noGrades) :codeStud(code) {
this->noGrades = noGrades;
this->grades = new int[noGrades];
for (int i = 0; i < noGrades; i++)
this->grades[i] = grades[i];
}
Student(const Student&existent):codeStud(existent.codeStud) {
this->noGrades = existent.noGrades;
this->grades = new int[this->noGrades];
for (int i = 0; i < this->noGrades; i++)
this->grades[i] = existent.grades[i];
}
int getCode() {
return this->codeStud;
}
int getNoGrades() {
return this->noGrades;
}
void setGrades(int grades[],int noGrades) {
this->noGrades = noGrades;
this->grades = new int[noGrades];
for (int i = 0; i < noGrades; i++)
this->grades[i] = grades[i];
}
};
void main() {
Student s1(101);
cout<<s1.getNoGrades();
int grades[] = { 10,7,8,10,4 };
Student s2(104, grades, 5);
cout << "\n" << s2.getNoGrades();
Student s3 = s2;
cout << "\n" << s3.getCode();
int grades2[] = { 5,5,4,10 };
s1.setGrades(grades2,4);
cout << "\n" << s1.getNoGrades(); // here is the problem
}
After I changed the grades for student 1 it shows that he has 0 grades, when the output should be 4, the number of these grades: 5,5,4,10.
The rest of output is correct, even when I want to know the number of grades for student 1, which is 0 , and then for student 2, which is 5.
I've changed some things in your code to compile it
#include<iostream>
#include<string>
using namespace std;
class Student {
public:
int codeStud;
int noGrades = 0;
int* grades = NULL;
Student(int code) {
codeStud = code;
}
Student(int code, int* grades, int noGrades) {
this->noGrades = noGrades;
this->grades = new int[noGrades];
for (int i = 0; i < noGrades; i++)
this->grades[i] = grades[i];
}
Student(const Student&existent){
this->noGrades = existent.noGrades;
this->grades = new int[this->noGrades];
for (int i = 0; i < this->noGrades; i++)
this->grades[i] = existent.grades[i];
}
int getCode() {
return this->codeStud;
}
int getNoGrades() {
return this->noGrades;
}
void setGrades(int grades[],int noGrades) {
this->noGrades = noGrades;
this->grades = new int[noGrades];
for (int i = 0; i < noGrades; i++)
this->grades[i] = grades[i];
}
};
int main() {
Student s1(101);
cout<<s1.getNoGrades();
int grades[] = { 10,7,8,10,4 };
Student s2(104, grades, 5);
cout << "\n" << s2.getNoGrades();
Student s3 = s2;
int grades2[] = { 5,5,4,10 };
s1.setGrades(grades2,4);
cout << "\n" << s1.getNoGrades(); // here is the problem
}
and output is:
0
5
4
what is correct, because you don't assign number of grades of s1 anywhere in your code before first printing
Also look for:
https://stackoverflow.com/questions/204476/what-should-main-return-in-c-and-c
why void main() is not correct
After I corrected the typo (codStud --> codeStud) your code produced the correct results for me. Before I did that I couldn't even compile it, so my guess would be that your IDE just run the latest working version of it that could be compiled successfully (look for error messages somewhere). That's the reason you got the wrong result, because your changes weren't even in that version.
A couple of note about your code:
In your setGrades function check that grades not pointing to something already. For example, if I call Student(int code, int* grades, int noGrades) and after I call setGrades your code leaks memory because it loses the array that Student(int code, int* grades, int noGrades) allocated before.
You should use vector instead of C-style arrays. It will make your code much more cleaner and less error-prone (see my example).
You could make your getter functions to const (like in my example), so it would be guaranteed that those functions don't change the value of any member of the class (you get a compile error if they do). Other than that, you can make the member variables to private.
Implementation using vectors:
#include <iostream> // cout
#include <vector> // vector
using namespace std;
class Student
{
public:
Student(const int code)
: m_code{code}
{
}
Student(const int code, const std::vector<int>& grades)
: m_code{code},
m_grades{grades}
{
}
// Default copy constructor is sufficient because the class can be copied
// memberwise.
int getCode() const {
return m_code;
}
int getNoGrades() const {
return m_grades.size();
}
void setGrades(const std::vector<int>& grades) {
m_grades = grades;
}
private:
const int m_code;
std::vector<int> m_grades;
};
int main()
{
Student s1(101);
cout << s1.getNoGrades();
Student s2(104, {10, 7, 8, 10, 4});
cout << "\n" << s2.getNoGrades();
Student s3 = s2;
cout << "\n" << s3.getCode();
s1.setGrades({5, 5, 4, 10});
cout << "\n" << s1.getNoGrades();
return 0;
}

how do i create an array where each element in the array, of size 10, is pointing to an object, in C++?

for example lets have a class or struct name Employee with two constructors, a default constructor and a constructor with parameters two strings and an int. why doesn't the following code work?
Employee *employees = (employee*) malloc(sizeof(Employee)*10);
let's say we have an array, size 10, of type string for first name, last name, and one of type int for salary. how to initialize the data members of each object class using the constructor with the parameters?
for (int i = 0; i < 10; i++)
{
employees[i] = employee(firstname[i], lastname[i], salary[i]);
}
I've been trying to do this for a few days now but wasn't successful. Also, can anyone tell how to do this using c++'s new and delete operator? and also is there a way this can be done using vectors?
Thank you
header file
class employee{
std::string firstname;
std::string lastname;
int salary;
public:
employee(std::string, std::string , int);
employee();
void setFirst(std::string);
void setLast(std::string);
void setSalary(int);
std::string getFirst();
std::string getLast();
int getSalary();
};
employee::employee(std::string x, std::string y, int z)
{
setFirst(x);
setLast(y);
setSalary(z);
}
void employee::setFirst(std::string x)
{
firstname = x;
}
void employee::setLast(std::string y)
{
lastname = y;
}
void employee::setSalary(int z)
{
salary = z > 0 ? z : 0;
}
std::string employee::getFirst()
{
return firstname;
}
std::string employee::getLast()
{
return lastname;
}
int employee::getSalary()
{
return salary;
}
.cpp file
#define MAX 20
using namespace std;
int main(int argc, char* argv[])
{
int n = 1;
cout << "number of employees: ";
cin >> n;
string firstname[MAX];
string lastname[MAX];
double salary[MAX];
float raise[MAX];
for (int i = 0; i < n; i++)
{
cout << "Employee " << i + 1 <<endl;
cout << "-----------\n";
cout << "First Name: ";
cin >> firstname[i];
cout << "Last Name: ";
cin >> lastname[i];
cout << "Monthly Salary: ";
cin >> salary[i];
salary[i] *= 12;
cout <<"Yearly percentage raise (e.g 10% or 0%): ";
scanf("%f%%", &raise[i]);
salary[i] *= (((raise[i])/100.00) + 1);
puts("\n");
}
employee *employees = (employee*) malloc(sizeof(employee)*10);
for (int i = 0; i < n; i++)
{
employees[i] = employee(firstname[i], lastname[i], salary[i]);
}
cout << "TESING USING GET FUNCTIONS" << endl;
cout << "---------------------------\n\n";
for (int i = 0; i < n; i++)
{
cout << "Employee " <<i +1<< endl;
cout <<"-----------\n";
printf("First Name: %s", employees[i].getFirst().c_str());
printf("\nLast Name: %s",employees[i].getLast().c_str());
printf("\nYearly Salary: %d\n\n", employees[i].getSalary());
}
}
If you have an array of Employee instances and Employee is not POD (http://en.wikipedia.org/wiki/POD) you need to allocate memory from the stack using the operator new:
Employee* employees = new Employee[10];
And for having this working:
for (int i = 0; i < 10; i++)
{
employees[i] = Employee(firstname[i], lastname[i], age[i]);
}
you need to implement the operator= in your Employee class:
Employee& operator=(const Employee& src)
{
_firstname = src._firstname;
_lastname = src._lastname;
_age = src._age;
return *this;
}
If this looks like your Employee class:
class Employee
{
std::string first_name;
std::string last_name;
// other members and functions ...
};
Then using malloc() to create 10 of these is a complete and utter failure. The reason why is that yes, you allocated memory using malloc(), but that's all you did. You didn't construct 10 Employee objects. Those std::string members need to be constructed, not merely have memory allocated. So with that call to malloc() you have 10 fake Employees that were "created", and as soon as you attempt to do anything with one of them, then boom goes your program.
Do research on POD and non-POD types. You cannot treat non-POD types (as the class above is non-POD) as you would a POD type. For a non-POD type, the instance must be "officially" constructed, (the constructor must be invoked).
On the other hand, malloc() knows nothing concerning C++ and what is required to create an object correctly via construction. All malloc (and calloc, and realloc) knows is to allocate bytes and return a pointer to the allocated space.
Use a vector instead, it's resizable, it's easier to manage, and as Grady stated in his comment, it's also generally not good practice to use malloc in C++ code (although it's possible). Maybe do something that looks like this:
#include <vector>
...
int size = 10;
std::vector<Employee *> employees;
for(int i = 0; i < size; i++)
{
//as far as pulling in your data, that depends on where it's coming from
Employee *temp = new Employee(...);
employees.push_back(temp);
}
I'm rusty on my C++ but this should work.
Try this way:
#include <iostream>
class Employee
{
std::string m_firstname;
std::string m_lastname;
int m_age;
public:
Employee()
{
m_firstname=m_lastname="";
m_age=0;
}
void setFirstName(std::string firstname)
{
m_firstname=firstname;
}
void setLastName(std::string lastname)
{
m_lastname=lastname;
}
void setAge(int age)
{
m_age=age;
}
void displayEmp()
{
std::cout<<m_firstname;
std::cout<<m_lastname;
std::cout<<m_age;
}
};
int main()
{
std::string fname;
std::string lname;
int age;
Employee *employee = new Employee[10];
Employee *employeeptr=employee;
for(int i=0;i<10;i++)
{
std::cin>>fname;
std::cin>>lname;
std::cin>>age;
employeeptr->setFirstName(fname);
employeeptr->setLastName(lname);
employeeptr->setAge(age);
employeeptr++;
}
employeeptr=employee;
for(int i=0;i<10;i++)
{
employeeptr->displayEmp();
employeeptr++;
}
delete []employee;
return 0;
}