Access violation executing in classes with inheritance/ c++ - c++

I have a base class Participant and I need to sort object in array of participant by quantity of their prizes or diplomas. The virtual function get_data return this number. But whileI try to sort, i've got error Access violation executing in row with comparing 2 numbers.
if (p[j].Get_Data() < p[i].Get_Data()) {
This is my full code:
#include <iostream>
#include <string>
#include <vector>
using namespace std;
class Participant {
protected:
string name;
string surname;
vector <string> type;
int age;
public:
Participant() : name(""), surname(""), type(), age(0)
{}
Participant(string name, string surname, vector <string> type, int age) {
this->name = name;
this->surname = surname;
this->type = type;
this->age = age;
};
Participant(const Participant& other) : name(other.name), surname(other.surname), type(other.type), age(other.age)
{
}
Participant& operator=(const Participant& other)
{
name = other.name;
surname = other.surname;
type = other.type;
age = other.age;
return *this;
}
virtual int Get_Data() {
return 0;
}
friend void Sort(Participant* p);
};
class Diploma : public Participant {
protected:
vector<int> places;
vector <string> type_d;
public:
Diploma() : places(), type_d{}
{}
Diploma(string name, string surname, vector <string> type, int age, vector<int> places, vector <string> type_d);
int Get_Data() override {
cout << "diplom prize" << endl;
cout << type_d.size() << endl;
return type_d.size();
}
};
class Prize : public Participant {
protected:
vector <int> places;
vector<string> prize;
public:
Prize(string name, string surname, vector <string> type, int age, vector<int> places, vector<string> prize);
int Get_Data() override{
cout << "Cont prize" << endl;
cout << prize.size() << endl;
return prize.size();
}
};
Prize::Prize(string name, string surname, vector <string> type, int age, vector<int> places, vector<string> prize) {
this->name = name;
this->surname = surname;
this->type = type;
this->age = age;
this->places = places;
this->prize = prize;
}
Diploma::Diploma(string name, string surname, vector <string> type, int age, vector<int> places, vector <string> type_d){
this->name = name;
this->surname = surname;
this->type = type;
this->age = age;
this->places = places;
this->type_d = type_d;
}
void Sort(Participant* p) {
Participant temp;
for (int i = 0; i < 3; i++) {
for (int j = i + 1; j < 3; j++)
{
if (p[j].Get_Data() < p[i].Get_Data()) {
temp = p[i];
p[i] = p[j];
p[j] = temp;
}
}
}
}
int main() {
Participant* pa[3];
pa[0] = new Diploma("Alex", "Smith", { "Geo","Math" }, 17, { 1,6 }, { "first"});
pa[1] = new Prize("Helen", "Blink", { "IT","Math" }, 18, { 2,2 }, {"Golden medal", "medal"});
pa[2] = new Prize("Brandon", "Brown", { "IT","Math" }, 18, { 2,2 }, { "Golden medal", "medal","gold"});
Sort(*pa);
for (int i = 0; i < 3; i++) {
pa[i]->Get_Data();
cout << endl;
}
}

The issue here is that when you are passing *pa, only the first element is accessible. If you run it in debug mode you will be able to see that inside sort function, p[1] is not a valid object. Basically, only p[0] is passed to the function. You should pass the reference to the array i.e. **pa to the sort function
void Sort(Participant **p)
{
Participant *temp;
for (int i = 0; i < 3; i++)
{
for (int j = i + 1; j < 3; j++)
{
if (p[j]->Get_Data() < p[i]->Get_Data())
{
temp = p[i];
p[i] = p[j];
p[j] = temp;
}
}
}
}
int main()
{
Participant *pa[3];
pa[0] = new Diploma("Alex", "Smith", {"Geo", "Math"}, 17, {1, 6}, {"first"});
pa[1] = new Prize("Helen", "Blink", {"IT", "Math"}, 18, {2, 2}, {"Golden medal", "medal"});
pa[2] = new Prize("Brandon", "Brown", {"IT", "Math"}, 18, {2, 2}, {"Golden medal", "medal", "gold"});
Sort(pa);
for (int i = 0; i < 3; i++)
{
pa[i]->Get_Data();
cout << endl;
}
}

Related

C++, pointers, exception thrown: read access violation. this was 0xFFFFFFFFFFFFFF5F

I am working on a school project that is all about pointers. I have been setting variables that string just fine but when I arrived at an int it throws
Exception thrown: read access violation. this was 0xFFFFFFFFFFFFFF5F
I am not sure what this particular variable age is a problem and the rest were fine.
I tried to set int age = 0; to initialize it somehow but no success. Here is the screenshot and the files if that helps narrow down the issue.
Student.cpp
#pragma once
#include <string>
#include <iostream>
#include "student.h"
#include "degree.h"
using namespace std;
// Accessors
string Student::getStudent_ID()
{
return Student_ID;
}
string Student::getFirst_Name()
{
return First_Name;
}
string Student::getLast_Name()
{
return Last_Name;
}
string Student::getEmail_Address()
{
return Email_Address;
}
int Student::getAge()
{
return age;
}
int* Student::getNumber_Days()
{
return Number_Days;
}
DegreeProgram Student::getDegreeProgram()
{
return degreeProgram;
}
//Mutators
void Student::setStudent_ID(string student_ID)
{
this->Student_ID = Student_ID;
}
void Student::setFirst_Name(string first_Name)
{
this->First_Name = First_Name;
}
void Student::setLast_Name(string last_Name)
{
this->Last_Name = Last_Name;
}
void Student::setEmail_Address(string email_Address)
{
this->Email_Address = Email_Address;
}
void Student::setAge(int age)
{
this->age = age;
}
void Student::setNumber_Days(int* Number_Days)
{
this->Number_Days[0] = Number_Days[0];
this->Number_Days[1] = Number_Days[1];
this->Number_Days[2] = Number_Days[2];
}
void Student::setDegreeProgram(DegreeProgram degreeProgram)
{
this->degreeProgram = degreeProgram;
}
//Constructor - essentually the same as a group of setters
Student::Student(string Student_ID, string First_Name, string Last_Name, string Email_Address, int age, int Number_Days[], DegreeProgram degreeProgram)
{
this->Student_ID = Student_ID;
this->First_Name = First_Name;
this->Last_Name = Last_Name;
this->Email_Address = Email_Address;
this->age = age;
this->Number_Days[0] = Number_Days[0];
this->Number_Days[1] = Number_Days[1];
this->Number_Days[2] = Number_Days[2];
this->degreeProgram = degreeProgram;
}
void Student::print()
{
cout << Student_ID << "\t" << First_Name << "\t" << Last_Name << "\t" << age << "\t" << Number_Days[0] << "\t" << Number_Days[1] << "\t" << Number_Days[2] << "\t" << degreeProgram << endl;
}
the Student.h file
#pragma once
#include <string>
#include <iostream>
#include "degree.h"
using namespace std;
class Student
{
private:
string Student_ID;
string First_Name;
string Last_Name;
string Email_Address;
int age;
int* Number_Days = 0;
DegreeProgram degreeProgram;
public:
//initialize need help
// accessors
Student(string Student_ID, string First_Name, string Last_Name, string Email_Address, int age, int Number_Days[], DegreeProgram degreeProgram);
string getStudent_ID();
string getFirst_Name();
string getLast_Name();
string getEmail_Address();
int getAge();
int* getNumber_Days();
DegreeProgram getDegreeProgram();
// mutators
void setStudent_ID(string);
void setFirst_Name(string);
void setLast_Name(string);
void setEmail_Address(string);
void setAge(int);
void setNumber_Days(int Number_Days[]);
void setDegreeProgram(DegreeProgram degreeProgram);
void print();
~Student();
};
Roster.cpp
#pragma once
#include <string>
#include <iostream>
#include <stdlib.h>
#include "student.h"
#include "degree.h"
#include "roster.h"
using namespace std;
//Student* classRosterArray[5];
//void add(string Student_ID, string First_Name, string Last_Name, string Email_Address, int Age, int Number_Days[], DegreeProgram degreeProgram);
//Student* classRosterArray[5]; //string studentData() = 0;
const string studentData[] =
{ "A1,John,Smith,John1989#gm ail.com,20,30,35,40,SECURITY",
"A2,Suzan,Erickson,Erickson_1990#gmailcom,19,50,30,40,NETWORK",
"A3,Jack,Napoli,The_lawyer99yahoo.com,19,20,40,33,SOFTWARE",
"A4,Erin,Black,Erin.black#comcast.net,22,50,58,40,SECURITY",
"A5,Rebekah,Johnson,rjoh804#wgu.edu,27,35,56,65,SOFTWARE" };
//2.E Looping through StudentData and parsing it
//Student* classRosterArray[];
void Roster::add(string Student_ID, string First_Name, string Last_Name, string Email_Address, int age, int Number_Days1, int Number_Days2, int Number_Days3, DegreeProgram degreeProgram)
//void Roster::parsingStudentData()
{
for (int i = 0; i < 5; i++)
{
//string studentData[];
int rhs = studentData[i].find(",");
classRosterArray[i]->setStudent_ID(studentData[i].substr(0, rhs));
int lhs = rhs + 1;
rhs = studentData[i].find(",", lhs);
classRosterArray[i]->setFirst_Name(studentData[i].substr(lhs, rhs - lhs));
lhs = rhs + 1;
rhs = studentData[i].find(",", lhs);
classRosterArray[i]->setLast_Name(studentData[i].substr(lhs, rhs - lhs));
lhs = rhs + 1;
rhs = studentData[i].find(",", lhs);
classRosterArray[i]->setEmail_Address(studentData[i].substr(lhs, rhs - lhs));
lhs = rhs + 1;
rhs = studentData[i].find(",", lhs);
classRosterArray[i]->setAge(stoi(studentData[i].substr(lhs, rhs - lhs))); // Made the string an int with "stoi"// help
//int NumberDays[Student::Number_Days];
lhs = rhs + 1;
rhs = studentData[i].find(",", lhs);
int NumberDays1 = stoi(studentData[i].substr(lhs, rhs - lhs));
lhs = rhs + 1;
rhs = studentData[i].find(",", lhs);
int NumberDays2 = stoi(studentData[i].substr(lhs, rhs - lhs));
lhs = rhs + 1;
rhs = studentData[i].find(",", lhs);
int NumberDays3 = stoi(studentData[i].substr(lhs, rhs - lhs));
int NumberDays[3] = { NumberDays1, NumberDays2, NumberDays3 };
classRosterArray[i]->setNumber_Days(NumberDays);
//Enum type
lhs = rhs + 1;
rhs = studentData[i].find(",", lhs);
//TO FINISH, THIS NEEDs TO BE REFINED, WE do not have the word in between defined"studentData[i].substr(lhs, rhs - lhs)" done
if (studentData[i] == "SECURITY")
classRosterArray[i]->setDegreeProgram(SECURITY);
else if (studentData[i] == "SOFTWARE")
classRosterArray[i]->setDegreeProgram(SOFTWARE);
else
classRosterArray[i]->setDegreeProgram(NETWORK);
}
//void Roster::add();
}
void Roster::remove(string Student_ID)
{
for (int i = 0; i < 5; i = i + 1)
{
if (Student_ID == classRosterArray[i]->getStudent_ID())
{
classRosterArray[i] = nullptr;
}
else
{
cout << "Error:Student not found" << endl;
}
}
}
void Roster::printAll()
{
for (int i = 0; i < 5; i = i + 1)
{
this->classRosterArray[i]->print();
//cout << Student_ID << /t << First_Name << /t << Last_Name << /t << Age << /t << Number_Days[] <<
}
}
void Roster::printAverageDaysInCourse(string Student_ID)
{
for (int i = 0; i < 5; i = i + 1)
{
//this->classRosterArray[i]->getNumber_Days();
//int* Number_Days[] = classRosterArray[i]->getNumber_Days();
int AvgDays = (classRosterArray[i]->getNumber_Days()[0] + classRosterArray[i]->getNumber_Days()[1] + classRosterArray[i]->getNumber_Days()[2]) / 3;
cout << Student_ID << ": " << AvgDays << endl;
}
}
void Roster::printInvalidEmails()
{
for (int i = 0; i < 5; i = i + 1)
{
string Email_Check = classRosterArray[i]->getEmail_Address();
string StudentID = classRosterArray[i]->getStudent_ID();
if (Email_Check.find("#") == string::npos or Email_Check.find(".") == string::npos or Email_Check.find(" ") != string::npos)
{
cout << StudentID << ": Invalid Email" << endl;
}
}
}
void Roster::printByDegreeProgram(DegreeProgram degreeProgram)
{
for (int i = 0; i < 5; i = i + 1)
{
if (classRosterArray[i]->getDegreeProgram() == degreeProgram)
{
classRosterArray[i]->print();
}
}
}
Roster.h
#pragma once
#include <string>
#include <iostream>
#include "student.h"
#include "degree.h"
using namespace std;
class Roster
{
Student* classRosterArray[5]; // = { 0,0,0 }; // Array holding Student data table information
void inicializeArray()
{
classRosterArray[0] = 0; // elements of the array initialized to 0
classRosterArray[1] = 0;
classRosterArray[2] = 0;
classRosterArray[3] = 0;
classRosterArray[4] = 0;
}
void parsingStudentData();
//classRosterArray=(Student1, Student2, )
// classRosterArray[2] = 37; // sets Student3 to 37 // to access the variables in classRosterArray
//Roster* classRosterArray[] = { "Student_ID", "First_Name", "Last_Name", "Email_Address", " Age", " Number_Days[]", "DegreeProgram"};
public:
void add(string Student_ID, string First_Name, string Last_Name, string Email_Address, int Age, int Number_Days1, int Number_Days2, int Number_Days3, DegreeProgram degreeProgram);
void remove(string Student_ID);
void printAll();
void printAverageDaysInCourse(string Student_ID);
void printInvalidEmails();
void printByDegreeProgram(DegreeProgram degreeProgram);
};

Sorting class array in ascending order

Quite new to programming and in need of some help, I'm looking to sort an class array in ascending order based on age, but I can only get the code to work in descending order. I may be overlooking something small since I've worked on this far too long so I'd appreciate any help!
#include <iostream>
#include <string>
using namespace std;
class Person
{
public:
string name;
int age;
Person(string name = "empty", int age = 0)
{
setName(name);
setAge(age);
}
void setName(string x) {
name = x;
}
string getName() {
return name;
}
void setAge(int y) {
age = y;
}
int getAge() {
return age;
}
void displayinfo()
{
cout << "Name: " << name; cout << " Age: " << age << endl;
}
};
void swap(Person &p, Person &q)
{
Person temp;
temp.name = p.name;
temp.age = p.age;
p.name = q.name;
p.age = q.age;
q.name = temp.name;
q.age = temp.age;
}
int main()
{
int userValue;
Person po("Jessica", 24);
Person po2("Robert", 49);
Person po3("Maria", 47);
Person po4("John", 19);
Person family[4] = {po,po2,po3,po4};
int sort(family[4].getAge());
{
for(int i = 0; i < 3; i++)
if (family[i].getAge() < family[i+1].getAge())
{
swap(family[i], family[i+1]);
}
}
for(int i = 0; i < 4; i++)
family[i].displayinfo();
}
int sort(family[4].getAge()); is not a function declaration (and you can't implement a function inside of another function). It is actually a variable declaration. It is declaring a variable int sort that is initialized with the value from family[4].getAge() (which is undefined behavior since index 4 is out of bounds of your family[] array).
So, you are declaring an unused sort variable, and then you enter your for(int i = 0; i < 3; i++) loop, which DOES NOT perform a full sort of the array. For what you are attempting, use the standard std::sort() algorithm instead, eg:
#include <iostream>
#include <string>
#include <algorithm>
using namespace std;
class Person
{
public:
string name;
int age;
Person(string name = "empty", int age = 0)
{
setName(name);
setAge(age);
}
void setName(string x) {
name = x;
}
string getName() const {
return name;
}
void setAge(int y) {
age = y;
}
int getAge() const {
return age;
}
void displayinfo() const
{
cout << "Name: " << name; cout << " Age: " << age << endl;
}
};
int main()
{
Person po1("Jessica", 24);
Person po2("Robert", 49);
Person po3("Maria", 47);
Person po4("John", 19);
Person family[4] = {po1, po2, po3, po4};
std::sort(family, family + 4,
[](const Person &p1, const Person &p2) {
return p1.getAge() < p2.getAge();
}
);
for(int i = 0; i < 4; i++) {
family[i].displayinfo();
}
return 0;
}
Live Demo
Note that your family[] array holds copies of the Person objects that you initialize it with. To avoid the overhead of those copies, you can sort pointers instead, eg:
int main()
{
Person po1("Jessica", 24);
Person po2("Robert", 49);
Person po3("Maria", 47);
Person po4("John", 19);
Person* family[4] = {&po1, &po2, &po3, &po4};
std::sort(family, family + 4,
[](const Person *p1, const Person *p2) {
return p1->getAge() < p2->getAge();
}
);
for(int i = 0; i < 4; i++) {
family[i]->displayinfo();
}
return 0;
}
Live Demo
Or, you can get rid of the individual p0... objects altogether and initialize the array directly instead, eg:
int main()
{
Person family[4]{
{"Jessica", 24},
{"Robert", 49},
{"Maria", 47},
{"John", 19}
};
std::sort(family, family + 4,
[](const Person &p1, const Person &p2) {
return p1.getAge() < p2.getAge();
}
);
for(int i = 0; i < 4; i++) {
family[i].displayinfo();
}
return 0;
}
Live Demo

Reserve dynamic memory with the new operator

I'm learning new operator and I have the next question:
I want to reserve new memory when I add a new subject and if I do this way I lose all the previus content of array.
So, how can I do this if i have to reserve memory each time that i want to add a new subject? Or in other words, how i reserve memory without lose the previus?
#include <iostream>
#include <stdlib.h>
#include <string.h>
#include <string>
using namespace std;
class Subject {
public:
Subject() { m_name = "";
m_hours = 0;
}
string getName() { return m_name; }
int getHours() { return m_hours; }
void setName(string name) { m_name = name; }
void setHours(int hours) { m_hours = hours; }
private:
string m_name;
int m_hours;
};
class Person {
private:
string m_name;
int m_age;
Subject *m_subjects;
int m_nSubjects;
public:
Person() {
m_name = "";
m_age = 0;
m_nSubjects = 0;
}
~Person() {
}
string getName() { return m_name; }
int getAge() { return m_age; }
void setName(string name) {
m_name = name;
}
void setAge(int age) {
m_age = age;
}
void addSubject(string name, int hour);
void showSubjects();
};
void Person::addSubject(string name, int hours) {
m_subjects = new Subject[m_nSubjects+1]; *the problem is here, all the previus content is lost*
m_subjects[m_nSubjects].setName(name);
m_subjects[m_nSubjects].setHours(hours);
m_nSubjects++;
}
void Person::showSubjects() {
for (int i = 0; i < m_nSubjects; i++) {
cout << m_subjects[i].getName();
cout << "\n";
cout << m_subjects[i].getHours();
}
}
int main() {
int nSubjects;
string name;
int hours;
Person person1;
person1.setName("Name 1");
person1.setAge(30);
cout << "Subjects to add: ";
cin >> nSubjects;
for (int i = 0; i < nSubjects; i++) {
cout << "Name of subject: " << "\n" << endl;
cin >> name;
cout << "Hours: " << "\n" << endl;
cin >> hours;
person1.addSubject(name, hours);
}
person1.showSubjects();
system("pause");
return 0;
}
I hope you can understand me.
You need to copy the existing data to the new array before you then replace the previous array (which you are leaking, BTW), eg:
void Person::addSubject(string name, int hours) {
Subject *new_subjects = new Subject[m_nSubjects+1];
for(int i = 0; i < m_nSubjects; ++i) {
new_subjects[i] = m_subjects[i];
}
new_subjects[m_nSubjects].setName(name);
new_subjects[m_nSubjects].setHours(hours);
delete[] m_subjects;
m_subjects = new_subjects;
m_nSubjects++;
}
You also need to free the current array in your Person destructor to avoid leaking as well:
~Person() {
delete[] m_subjects;
}
And you also need to add a copy constructor and a copy assignment operator to Person as well, to avoid future problems with multiple Person objects sharing the same array in memory if you assign one Person to another:
Person(const Person &src) {
m_name = src.m_name;
m_age = src.m_age;
m_nSubjects = src.m_nSubjects;
m_subjects = new Subject[m_nSubjects];
for (int i = 0; i < m_nSubjects; ++i) {
m_subjects[i] = src.m_subjects[i];
}
}
Person& operator=(const Person &rhs) {
if (&rhs != this) {
Person copy(rhs);
std::swap(m_name, copy.m_name);
std::swap(m_age, copy.m_age);
std::swap(m_nSubjects, copy.m_nSubjects);
std::swap(m_subjects, copy.m_subjects);
}
return *this;
}
And, if you are using C++11 or later, you should (optionally) also add a move constructor and move assignment operator to Person, too:
Person(Person &&src) {
m_name = std::move(src.m_name);
m_age = src.m_age; src.m_age = 0;
m_nSubjects = src.m_nSubjects; src.m_nSubjects = 0;
m_subjects = src.m_subjects; src.m_subjects = nullptr;
}
Person& operator=(Person &&rhs) {
Person movedTo(std::move(rhs));
std::swap(m_name, movedTo.m_name);
std::swap(m_age, movedTo.m_age);
std::swap(m_nSubjects, movedTo.m_nSubjects);
std::swap(m_subjects, movedTo.m_subjects);
return *this;
}
See the Rule of 3/5/0 for more details.
A better solution is to use std::vector instead, let the compiler handle all of these details for you:
#include <iostream>
#include <string>
#include <vector>
#include <limits>
class Subject {
public:
Subject() {
m_name = "";
m_hours = 0;
}
Subject(std::string name, int hours) {
m_name = name;
m_hours = hours;
}
std::string getName() const { return m_name; }
int getHours() const { return m_hours; }
void setName(std::string name) { m_name = name; }
void setHours(int hours) { m_hours = hours; }
private:
std::string m_name;
int m_hours;
};
class Person {
private:
std::string m_name;
int m_age;
std::vector<Subject> m_subjects;
public:
Person() {
m_name = "";
m_age = 0;
}
std::string getName() const { return m_name; }
int getAge() const { return m_age; }
void setName(std::string name) { m_name = name; }
void setAge(int age) { m_age = age; }
void addSubject(std::string name, int hour);
void showSubjects() const;
};
void Person::addSubject(string name, int hours) {
m_subjects.push_back(Subject(name, hours));
}
void Person::showSubjects() const {
for (std::size_t i = 0; i < m_nSubjects.size(); ++i) {
cout << m_subjects[i].getName();
cout << "\n";
cout << m_subjects[i].getHours();
}
}
int main() {
int nSubjects;
std::string name;
int hours;
Person person1;
person1.setName("Name 1");
person1.setAge(30);
std::cout << "Subjects to add: ";
std::cin >> nSubjects;
for (int i = 0; i < nSubjects; i++) {
std::cout << "Name of subject: ";
std::getline(std::cin, name);
std::cout << "Hours: ;
std::cin >> hours;
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
person1.addSubject(name, hours);
}
person1.showSubjects();
std::system("pause");
return 0;
}

C++ Memory Leaks with my std::map of &Objects and std::vector of &Objects

Basically I have this
std::map<std::string, Location&> exits = std::map<std::string, Location&>();
As a private member in a class. And I am unsure about how I would delete it to free the memory when the object of the class gets deleted
I also have a lot of vectors like this
std::vector<Item> Ritems;
Which I am also unsure how to delete, the vector gets Objects& added to it
Deleaker gives me around 1000 of the following:
xmemory0, line 89 (c:\program files (x86)\microsoft visual studio 14.0\vc\include\xmemory0)
Location object
class Object;
class Location
{
public:
Location();
Location(std::string RoomName, std::string RoomDesc);
~Location();
Location(const Location& e);
void AddExit(std::string Direction, Location &Room);
void AddItem(Item &Items);
void AddObject(Object &Objects);
void RemoveObject(std::string ObjName);
void AddNPC(NPC &NPCs);
void PickUpItem(Character &CurChar, std::string ItemName);
void DisplayAll();
void DisplayExits();
void DisplayItems();
void DisplayObjects();
void DisplayNPCs();
std::string GetName();
std::string GetDesc();
Location GoCommand(std::string Direction);
void TalkCommand(std::string Communication, Character &MainCharacter);
Location operator=(const Location &other);
Object CheckObject(std::string Command, std::string ObjName);
private:
std::string Name;
std::string Description;
std::map<std::string, Location&> exits = std::map<std::string, Location&>();
std::vector<Item> Ritems;
std::vector<Object> Robjects;
std::vector<NPC> RNPC;
};
#include <iostream>
#include "Locations.h"
#include <regex>
#include "Object.h"
Location::Location()
{
Name = "";
Description = "";
}
Location::Location(std::string RoomName, std::string RoomDesc)
{
Name = RoomName;
Description = RoomDesc;
}
Location::~Location()
{
}
Location::Location(const Location& e)
{
Name = e.Name;
Description = e.Description;
exits = e.exits;
Ritems = e.Ritems;
Robjects = e.Robjects;
RNPC = e.RNPC;
}
void Location::AddExit(std::string Direction, Location &Room)
{
exits.insert(std::pair<std::string, Location*>(Direction, &Room));
}
void Location::AddItem(Item &Items)
{
Ritems.push_back(Items);
}
void Location::AddObject(Object &Objects)
{
Robjects.push_back(Objects);
}
void Location::RemoveObject(std::string ObjName)
{
Object Temp;
std::transform(ObjName.begin(), ObjName.end(), ObjName.begin(), ::tolower);
for (int i = 0; i < Robjects.size(); i++)
{
std::string TempS = Robjects[i].GetName();
std::transform(TempS.begin(), TempS.end(), TempS.begin(), ::tolower);
if (TempS == ObjName)
Robjects.erase(Robjects.begin() + i);
}
}
void Location::AddNPC(NPC &NPCs)
{
RNPC.push_back(NPCs);
}
void Location::PickUpItem(Character &CurChar, std::string ItemName)
{
std::transform(ItemName.begin(), ItemName.end(), ItemName.begin(), ::tolower);
for (int i = 0; i < Ritems.size(); i++)
{
std::string Temp = Ritems[i].GetName();
std::transform(Temp.begin(), Temp.end(), Temp.begin(), ::tolower);
if (Temp == ItemName)
{
CurChar.AddItem(Ritems[i]);
Ritems.erase(Ritems.begin() + i);
}
}
}
Object Location::CheckObject(std::string Command, std::string ObjName)
{
Object Temp;
std::transform(Command.begin(), Command.end(), Command.begin(), ::tolower);
std::transform(ObjName.begin(), ObjName.end(), ObjName.begin(), ::tolower);
for (int i = 0; i < Robjects.size(); i++)
{
std::string TempS = Robjects[i].GetName();
std::transform(TempS.begin(), TempS.end(), TempS.begin(), ::tolower);
if (TempS == ObjName)
return Robjects[i];
}
return Temp;
}
void Location::DisplayAll()
{
WriteLine(7, '-');
DisplayElement(7, Description);
DisplayExits();
DisplayItems();
DisplayObjects();
DisplayNPCs();
WriteLine(7, '-');
}
void Location::DisplayExits()
{
DisplayElement(7, "|- You can travel; ");
for (std::map<std::string, Location*>::iterator ii = exits.begin(); ii != exits.end(); ++ii)
{
SetColour(7);
std::cout << "\t";
SetColour(112);
std::cout << "[" << (*ii).first << "]";
SetColour(8);
std::cout << " to " << (*ii).second->GetName() << std::endl;
}
}
void Location::DisplayItems()
{
int Count = 0;
if (Ritems.size() != 0)
{
DisplayElement(7, "Items in room: ");
for (int i = 0; i < Ritems.size(); i++)
{
DisplayElementWC(Count, 5, 13, Ritems[i].GetName());
DisplayElementWC(Count, 6, 14, Ritems[i].GetDesc());
DisplayElementWC(Count, 6, 14, Ritems[i].GetItemValue());
Count++;
}
}
}
void Location::DisplayObjects()
{
int Count = 0;
if (Robjects.size() != 0)
{
DisplayElement(7, "Objects in room: ");
for (int i = 0; i < Robjects.size(); i++)
{
DisplayElementWC(Count, 5, 13, Robjects[i].GetName());
DisplayElementWC(Count, 6, 14, Robjects[i].GetDesc());
}
}
}
void Location::DisplayNPCs()
{
int Count = 0;
if (RNPC.size() != 0)
{
DisplayElement(7, "NPCs in room: ");
for (int i = 0; i < RNPC.size(); i++)
{
DisplayElementWC(Count, 5, 13, RNPC[i].GetName());
DisplayElementWC(Count, 6, 14, RNPC[i].GetDesc());
}
}
}
std::string Location::GetName()
{
return Name;
}
std::string Location::GetDesc()
{
return Description;
}
Location Location::GoCommand(std::string Direction)
{
Location ReturnLoc = *this;
std::string Test;
std::transform(Direction.begin(), Direction.end(), Direction.begin(), ::tolower);
for (std::map<std::string, Location*>::iterator ii = exits.begin(); ii != exits.end(); ++ii)
{
Test = (*ii).first;
std::transform(Test.begin(), Test.end(), Test.begin(), ::tolower);
if (Test == Direction)
ReturnLoc = *(*ii).second;
}
return ReturnLoc;
}
void Location::TalkCommand(std::string Communication, Character &MainCharacter)
{
std::string Test;
std::transform(Communication.begin(), Communication.end(), Communication.begin(), ::tolower);
for (int i = 0; i < RNPC.size(); i++)
{
Test = RNPC[i].GetName();
std::transform(Test.begin(), Test.end(), Test.begin(), ::tolower);
if (Test == Communication)
{
RNPC[i].StartConvo(MainCharacter);
}
}
}
Location Location::operator=(const Location &other)
{
Name = other.Name;
Description = other.Description;
exits = other.exits;
Ritems = other.Ritems;
Robjects = other.Robjects;
RNPC = other.RNPC;
return *this;
}
Okay I hope this is a MCVE aha
#include <iostream>
#include <map>
#include <regex>
#include <string>
#include <windows.h>
#include <cctype>
//Custom Classes
class Location;
class UpdateLocation
{
public:
UpdateLocation();
~UpdateLocation();
void AddLocation(Location &Room);
void UpdateNow(Location &Room);
Location GetLocal(Location &Room);
private:
std::map<std::string, Location*> Locations = std::map<std::string, Location*>();
};
class Location
{
public:
Location();
Location(std::string RoomName, std::string RoomDesc);
~Location();
Location(const Location& e);
void AddExit(std::string Direction, Location &Room);
void DisplayExits();
std::string GetName();
std::string GetDesc();
Location operator=(const Location &other);
private:
std::string Name;
std::string Description;
std::map<std::string, Location*> exits = std::map<std::string, Location*>();
};
UpdateLocation::UpdateLocation()
{
}
UpdateLocation::~UpdateLocation()
{
}
void UpdateLocation::AddLocation(Location &Room)
{
Locations.insert(std::pair<std::string, Location*>(Room.GetName(), &Room));
}
void UpdateLocation::UpdateNow(Location &Room)
{
for (std::map<std::string, Location*>::iterator ii = Locations.begin(); ii != Locations.end(); ++ii)
{
if ((*ii).first == Room.GetName())
{
*(*ii).second = Room;
}
}
}
Location UpdateLocation::GetLocal(Location &Room)
{
for (std::map<std::string, Location*>::iterator ii = Locations.begin(); ii != Locations.end(); ++ii)
{
if ((*ii).first == Room.GetName())
{
return *(*ii).second;
}
}
}
Location::Location()
{
Name = "";
Description = "";
}
Location::Location(std::string RoomName, std::string RoomDesc)
{
Name = RoomName;
Description = RoomDesc;
}
Location::~Location()
{
}
Location::Location(const Location& e)
{
Name = e.Name;
Description = e.Description;
exits = e.exits;
}
void Location::AddExit(std::string Direction, Location &Room)
{
exits.insert(std::pair<std::string, Location*>(Direction, &Room));
}
void Location::DisplayExits()
{
std::cout << "|- You can travel; " << std::endl;
for (std::map<std::string, Location*>::iterator ii = exits.begin(); ii != exits.end(); ++ii)
{
std::cout << "\t";
std::cout << "[" << (*ii).first << "]";
std::cout << " to " << (*ii).second->GetName() << std::endl;
}
}
std::string Location::GetName()
{
return Name;
}
std::string Location::GetDesc()
{
return Description;
}
Location Location::operator=(const Location &other)
{
Name = other.Name;
Description = other.Description;
exits = other.exits;
return *this;
}
void main()
{
//Create GameWorld
UpdateLocation UpdateIt;
Location HallWay("Hallway", "Long corridor with a wide array of footboats");
getchar();
getchar();
}
First, you probably want to read this (for c++03 and earlier):
Why Can't I store references in an STL map in C++?
For c++11 and later it's actually possible to have references as values in std::maps using std::map::emplace(), but it's inconvenient and I cannot see it being as useful as raw pointers, which also should be replaced with std::unique_ptrs if the container object owns the objects placed in it.
You probably want
std::map<std::string, Location *> exits;
as your private member. There's no need to delete your map nor your vector. When the destructor of your class is called, the destructor of the respective object is called. They basically self-destruct. You explained that the exits object doesn't own the Location objects, so exits shouldn't have anything to do with deallocating memory allocated for them.

Array of derived class stored in parent class

I don't think I quite understand how to store an array of a derived class in its parent class.
I keep getting errors
Error C3646 'list': unknown override specifier
Error C2065 'list': undeclared identifier
Here is the code I have
#include <iostream>
#include <string>
using namespace std;
class GameScores
{
public:
GameEntry list[9];
void inputList(GameEntry x);
void sortList();
void removeList(int r);
void printList();
GameScores();
};
class GameEntry :public GameScores
{
public:
GameEntry(const string& n = "", int s = 0, const string d = "1/1/99");
string getName() const;
int getScore() const;
string getDate() const;
string setName(string n);
int setScore(int s);
string setDate(string d);
private:
string name;
int score;
string date;
};
GameScores::GameScores()
{
GameEntry list[9];
}
void GameScores::inputList(GameEntry x)
{
for (int i = 0; i < 10; i++)
if (x.getScore() >= list[i].getScore())
{
list[i + 1] = list[i];
list[i] = x;
}
}
void GameScores::sortList()
{
GameEntry swap;
for (int i = 0; i < 10; i++)
{
for (int j = 0; j < 10 - 1; j++)
{
if (list[j].getScore() > list[j].getScore() + 1)
{
swap = list[j];
list[j] = list[j + 1];
list[j + 1] = swap;
}
}
}
}
void GameScores::removeList(int r)
{
for (int i = r; i < 10; i++)
list[i - 1] = list[i];
list[9].setScore(0);
list[9].setName(" ");
list[9].setDate(" ");
}
void GameScores::printList()
{
cout << "Top Scores" << endl;
for (int i = 0; i < 10; i++)
cout << list[i].getScore() << " " << list[i].getName() << " " << list[i].getDate() << endl;
}
GameEntry::GameEntry(const string& n, int s, const string d) // constructor
: name(n), score(s), date(d) { }
// accessors
string GameEntry::getName() const { return name; }
int GameEntry::getScore() const { return score; }
string GameEntry::getDate() const { return date; }
string GameEntry::setName(string n)
{
name = n;
}
int GameEntry::setScore(int s)
{
score = s;
}
;
string GameEntry::setDate(string d)
{
date = d;
}
int main()
{
GameEntry p1("John", 90, "9/9/98"), p2("Jane", 95, 8/21/98), p3("Bob", 60, "7/11/99"), p4("Jo", 92, "6/4/97");
GameScores topScores;
topScores.inputList(p1);
topScores.inputList(p2);
topScores.inputList(p3);
topScores.inputList(p4);
topScores.printList();
return 0;
}
This design is very questionable. What purpose is being served by making the second class inherit the first? It looks like you'd end up with each member of the array containing an additional array with all its siblings. Don't you want only one array? You need to rethink this from an earlier point.
If you really have a reason for a parent class to contain an array of the child class, maybe you should define an interface (abstract base class) that both classes implement.
To use GameEntry as a type in your GameScores class , you must forward-declare the class like so :
class GameEntry;
class GameScores
{
public:
GameEntry list[9];
void inputList(GameEntry x);
void sortList();
void removeList(int r);
void printList();
GameScores();
};