Writing a Virtual Serialize Function with a Base and Derived Class - c++

I'm working on a project to handle an inventory of cars. There is a base Vehicle class and a derived AdvancedVehicle class. I am running into an issue with my serialize function which is meant to be a virtual function. It seems that whenever the function is called by either the base or derived class, it only runs the base serialize function. Attached is both the Vehicle and AdvancedVehicle class definitions and implementations.
/////////////////////////////// VEHICLE //////////////////////////////////
class Vehicle{
friend ostream& operator<< (ostream& os, const Vehicle v) {
v.Serialize(os);
return os;
}
public:
Vehicle() = delete;
Vehicle(string model, size_t year, float price) {
m_model = model;
m_year = year;
m_baseprice = price;
m_owner = NULL;
}
Vehicle(string model, size_t year, float price, const Client* owner) {
m_model = model;
m_year = year;
m_baseprice = price;
m_owner = new Client("");
*m_owner = *owner;
}
Vehicle(const Vehicle& otherVehicle) {
m_model = otherVehicle.m_model;
m_year = otherVehicle.m_year;
m_baseprice = otherVehicle.m_baseprice;
m_owner = NULL;
}
Vehicle& operator= (const Vehicle& otherVehicle) {
m_model = otherVehicle.m_model;
m_year = otherVehicle.m_year;
m_baseprice = otherVehicle.m_baseprice;
m_owner = new Client("");
*m_owner = *otherVehicle.m_owner;
return *this;
}
void setPrice(float price) {
m_baseprice = price;
}
void SetOwner(const Client* owner) {
m_owner = new Client("");
if(owner)
{
*m_owner = *owner;
}
}
string GetModel() const { return m_model; }
size_t GetYear() const { return m_year; }
virtual float GetPrice() const { return m_baseprice; }
Client* GetOwner() const { return m_owner; }
virtual void Serialize(ostream& os) const {
os << m_year << " ";
os << m_model << " ";
os << m_baseprice << " ";
if(m_owner != NULL)
{
os << *m_owner << endl;
}
}
protected:
string m_model;
size_t m_year;
private:
float m_baseprice;
Client* m_owner;
};
/////////////////////////// ADVANCEDVEHICLE ///////////////////////////////
class AdvancedVehicle : public Vehicle{
friend ostream& operator<< (ostream& os, const AdvancedVehicle AV) {
AV.Serialize(os);
return os;
}
public:
AdvancedVehicle() = delete;
AdvancedVehicle(string model, size_t year, float price, vector<Sensor> sensors, const Client* owner):Vehicle (model, year, price){
m_model = model;
m_year = year;
SetOwner(owner);
setPrice(price);
for(auto i = sensors.begin(); i != sensors.end(); i++)
{
int j = 0;
AddSensor(sensors[j]);
j++;
}
}
AdvancedVehicle(string model, size_t year, float price, vector<Sensor> sensors):Vehicle (model, year, price){
m_model = model;
m_year = year;
SetOwner(NULL);
setPrice(price);
for(auto i = sensors.begin(); i != sensors.end(); i++)
{
int j = 0;
AddSensor(sensors[j]);
j++;
}
}
AdvancedVehicle(const AdvancedVehicle& otherAV):Vehicle( otherAV) {
m_model = otherAV.m_model;
m_year = otherAV.m_year;
m_finalprice = otherAV.m_finalprice;
SetOwner(NULL);
for(auto i = otherAV.m_sensors.begin(); i != otherAV.m_sensors.end(); i++)
{
int j = 0;
AddSensor(otherAV.m_sensors[j]);
j++;
}
}
AdvancedVehicle& operator=(const AdvancedVehicle& otherAV) {
m_model = otherAV.m_model;
m_year = otherAV.m_year;
setPrice(otherAV.GetPrice());
SetOwner(otherAV.GetOwner());
for(auto i = otherAV.m_sensors.begin(); i != otherAV.m_sensors.end(); i++)
{
int j = 0;
AddSensor(otherAV.m_sensors[j]);
j++;
}
return *this;
}
void AddSensor(Sensor addedSensor) {
m_sensors.push_back(addedSensor);
m_finalprice += addedSensor.GetPrice();
}
virtual float GetPrice() const { return m_finalprice; }
virtual void Serialize(ostream& os) const {
os << m_year << " ";
os << m_model << " ";
os << m_finalprice << " ";
if(GetOwner() != NULL)
{
os << GetOwner() << " ";
}
for(auto i = m_sensors.begin(); i != m_sensors.end(); i++)
{
os << &i << " ";
}
os << endl;
}
private:
vector<Sensor> m_sensors;
float m_finalprice;
};

Your program is suffering from the object slicing problem. The operator<< takes a Vehicle object by value. This means a new Vehicle object is copy-constructed from the argument passed to the operator. The new object is a Vehicle, not an AdvancedVehicle, even if what was passed to the operator was an AdvancedVehicle. The object is said to have been sliced and this is why the base version of the Serialize() function is called.
To address this, you should modify the operator<< overload to take a Vehicle by reference (Vehicle&). This will eliminate the copy and the slicing.

Related

C++ - Overriden method not called properly (memory violation)

In my program I'm trying to create abstract class called "DMA", from which "BaseDMA" inherits from it. Then classes "LacksDMA" and "HasDMA" inherits from "BaseDMA".
Every class override method
readInfo() from "DMA". Here is the code:
dma.h
#ifndef DMA_H_
#define DMA_H_
#include <iostream>
class DMA
{
protected:
char * label;
public:
DMA(const char * l);
DMA & operator=(const DMA & anotherDMA);
virtual ~DMA();
virtual void readInfo() const = 0;
char * getLabel() const ;
};
class BaseDMA: public DMA
{
private:
int rating;
public:
BaseDMA(const char * l, int r = 0);
BaseDMA(const BaseDMA & anotherBaseDMA);
virtual ~BaseDMA();
BaseDMA & operator=(const BaseDMA & anotherBaseDMA);
void readInfo() const override;
};
class LacksDMA: public BaseDMA
{
private:
enum { COL_LEN = 40 };
char color[COL_LEN];
public:
LacksDMA(const char * c = "no color", const char * l = "no color", int r = 0);
LacksDMA(const LacksDMA & anotherLacksDMA);
LacksDMA & operator=(const LacksDMA & anotherLacksDMA);
void readInfo() const override;
};
class HasDMA: public BaseDMA
{
private:
char * style;
public:
HasDMA(const char * s = "lack", const char * l = "lack", int r = 0);
HasDMA(const HasDMA & anotherHasDMA);
~HasDMA();
HasDMA & operator=(const HasDMA & anotherHasDMA);
void readInfo() const override;
};
#endif DMA_H_
dma.cpp
#include <string.h>
DMA::DMA(const char * l)
{
this->label = new char[strlen(l)+1];
strcpy(this->label, l);
}
DMA & DMA::operator=(const DMA & anotherDMA)
{
if(this == &anotherDMA)
return * this;
delete [] this->label;
this->label = new char[strlen(anotherDMA.label)+1];
strcpy(this->label, anotherDMA.label);
return *this;
}
char * DMA::getLabel() const
{
return this->getLabel();
}
DMA::~DMA()
{
delete [] label;
}
BaseDMA::BaseDMA(const char * l, int r)
: DMA(l)
{
this->rating = r;
}
BaseDMA::BaseDMA( const BaseDMA & anotherBaseDMA)
: DMA(anotherBaseDMA.label)
{
this->rating = anotherBaseDMA.rating;
}
BaseDMA::~BaseDMA()
{
}
BaseDMA & BaseDMA::operator=(const BaseDMA & anotherBaseDMA)
{
if(this == &anotherBaseDMA)
return *this;
DMA::operator=(anotherBaseDMA);
this->rating = anotherBaseDMA.rating;
return *this;
}
void BaseDMA::readInfo() const
{
std::cout << "BaseDMA object:\n";
std::cout << "Label: " << this->getLabel() << std::endl;
std::cout << "Rating: " << this->rating << std::endl;
}
LacksDMA::LacksDMA(const char * c, const char * l, int r)
:BaseDMA(l,r)
{
strcpy(this->color, c);
}
LacksDMA::LacksDMA(const LacksDMA & anotherLacksDMA)
: BaseDMA(anotherLacksDMA)
{
strcpy(this->color, anotherLacksDMA.color);
}
LacksDMA & LacksDMA::operator=(const LacksDMA & anotherLacksDMA)
{
if(this == &anotherLacksDMA)
return *this;
DMA::operator=(anotherLacksDMA);
strcpy(this->color, anotherLacksDMA.color);
return * this;
}
void LacksDMA::readInfo() const
{
BaseDMA::readInfo();
std::cout << "LacksDMA object:\n";
std::cout << "Color: " << color << std::endl;
}
HasDMA::HasDMA(const char * s, const char * l, int r)
:BaseDMA(l, r)
{
this->style = new char[strlen(s)+1];
strcpy(this->style, s);
}
HasDMA::HasDMA(const HasDMA & anotherHasDMA)
:BaseDMA(anotherHasDMA)
{
this->style = new char[strlen(anotherHasDMA.style)+1];
strcpy(this->style, anotherHasDMA.style);
}
HasDMA::~HasDMA()
{
delete [] this->style;
}
HasDMA & HasDMA::operator=(const HasDMA & anotherHasDMA)
{
if(this == &anotherHasDMA)
return *this;
BaseDMA::operator=(anotherHasDMA);
delete [] this->style;
this->style = new char[strlen(anotherHasDMA.style)+1];
strcpy(this->style, anotherHasDMA.style);
return *this;
}
void HasDMA::readInfo() const
{
BaseDMA::readInfo();
std::cout << "HasDMA object:\n";
std::cout << "Style: " << this->style << std::endl;
}
main.cpp
#include "dma.h"
void menuPanel();
void printDMS(DMA ** dms, int count);
int main()
{
const int DMA_COUNT = 4;
DMA * dmas[DMA_COUNT];
for(int i = 0; i < DMA_COUNT; i++)
{
void menuPanel();
int choice;
do
{
(std::cin >> choice).ignore();
if(std::cin.bad())
std::cin.clear();
} while (choice < 1 || choice > 3);
std::cout << "Write label: ";
char label[40];
std::cin.getline(label, 40);
std::cout << "Write rating: ";
int rating;
(std::cin >> rating).ignore();
if(choice == 1)
{
dmas[i] = new BaseDMA(label,rating);
std::cout << std::endl;
}
else if(choice == 2)
{
std::cout << "Write color: ";
char color[40];
std::cin.getline(color,40);
dmas[i] = new LacksDMA(color, label, rating);
}
else // choice == 3
{
std::cout << "write style: ";
char style[40];
std::cin.getline(style,40);
dmas[i] = new HasDMA(style, label, rating);
}
}
for(int i = 0; i < DMA_COUNT; i++)
delete dmas[i];
}
void menuPanel()
{
std::cout << "Panel action:\n";
std::cout << "1) make BbaseDMA" << std::endl;
std::cout << "2) make LacksDMA" << std::endl;
std::cout << "3) make HasDMA" << std::endl;
std::cout << std::endl;
}
void printDMS(DMA ** dms, int count)
{
for(int i = 0; i < count; i++)
{
dms[i]->readInfo();
std::cout << std::endl;
}
}
When I try to use runtime polymorphism with by calling readInfo() method in main() I get message about memory violation.
What I'm doing wrong?
Thank you in advance for your answers.
There are a number of issues with your code, but your memory issue is here:
char * DMA::getLabel() const
{
return this->getLabel();
}
As soon as getLabel() is called, such as in BaseDMA::readInfo(), you enter an endless recursion loop that eventually overflows the call stack.
DMA::getLabel() should be returning this->label instead:
char * DMA::getLabel() const
{
return this->label;
}

How to make ostream operator for nested list in c++?

class CTurist
{
private:
string name;
string country;
int age;
public:
CTurist()
{
name = "";
country = "";
age = 0;
}
CTurist(string n, string c, int a)
{
name = n;
country = c;
age = a;
}
CTurist(const CTurist &t)
{
name = t.name;
country = t.country;
age = t.age;
}
string get_name()
{
return name;
}
string get_country()
{
return country;
}
int get_age()
{
return age;
}
void set_name(string n)
{
name = n;
}
void set_country(string c)
{
country = c;
}
void set_age(int a)
{
age = a;
}
bool operator<(CTurist& t)
{
return this->age < t.age;
}
friend istream& operator >> (istream& istr, CTurist& t)
{
istr >> t.name >> t.country >> t.age;
return istr;
}
friend ostream& operator<<(ostream& ostr, const CTurist& t)
{
ostr << "\nName: " << t.name << ", country: " << t.country << ", age: " << t.age;
return ostr;
}
};
class CHotel
{
private:
string hotel_name;
int num_beds;
double aver_price;
list<list<CTurist>>l;
public:
CHotel()
{
hotel_name = "";
num_beds = 0;
aver_price = 0;
}
CHotel(string hn, int nb, double ap, list<list<CTurist>>&lis)
{
hotel_name = hn;
num_beds = nb;
aver_price = ap;
l = lis;
}
CHotel(const CHotel& h)
{
hotel_name = h.hotel_name;
num_beds = h.num_beds;
aver_price = h.aver_price;
}
string get_hotel_name()
{
return hotel_name;
}
int get_num_beds()
{
return num_beds;
}
double get_aver_price()
{
return aver_price;
}
list<list<CTurist>> get_list_name() {
return l;
}
void set_hotel_name(string hn)
{
hotel_name = hn;
}
void set_num_beds(int nb)
{
num_beds = nb;
}
void set_aver_price(double ap)
{
aver_price = ap;
}
bool operator<(CHotel& h)
{
return this->aver_price < h.aver_price;
}
friend ostream& operator<<(ostream& ostr, const CHotel& h)
{
ostr << "Hotel name: " << h.hotel_name << ", number of beds: " << h.num_beds << ", average price: " << h.aver_price;
for(list<list<CTurist>>::iterator itr=h.l.begin();itr!=h.l.end();itr++)
{
for (list<CTurist>::iterator it = itr->begin(); it != itr->end(); it++)
ostr << *it;
}
return ostr;
}
}
As you see i have this 2 classes-CTurist and CHotel.
Everything with the first one is ok, but the problems came with the second.
I'm trying to make ostream operator for class CHotel works.
Everything else is working but only this operator is the problem.
I'm sure it is because of the nested list cuz it is new for me and maybe im somehow wrong.
If anyone knows how to do it, please tell me where is my mistake.
<br>And this is the error when im trying to debug it.It sure is from this nested list.
error C2440: 'initializing': cannot convert from 'std::_List_const_iterator<std::_List_val<std::_List_simple_types<_Ty>>>' to 'std::_List_iterator<std::_List_val<std::_List_simple_types<_Ty>>>' 1> with 1> [ 1> _Ty=std::list<CTurist,std::allocator<CTurist>> 1> ]
As h is a const CHotel&, you need const_iterator:
for (list<list<CTurist>>::const_iterator itr=h.l.begin();itr!=h.l.end();itr++)
{
for (list<CTurist>::const_iterator it = itr->begin(); it != itr->end(); it++)
ostr << *it;
}
Or simply use for range:
for (const auto& turists : h.l)
{
for (const auto& turist : turists)
ostr << turist;
}

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;
}

Segmentation Fault when trying to create a dynamically allocated char array

This is my code:
#include<iostream>
#include<string.h>
using namespace std;
class Zichara
{
private:
char *name;
int price;
void copy(const Zichara &from)
{
name = new char[strlen(from.name) + 1];
strcpy(name, from.name);
price = from.price;
}
public:
Zichara(const char *name, int price) {
this->name = new char[strlen(name) + 1];
strcpy(this->name, name);
this->price = price;
}
Zichara(const Zichara &from)
{
copy(from);
}
~Zichara() {
delete [] name;
}
friend class PlaninarskiDom;
};
class PlaninarskiDom {
private:
char name[15];
int prices[2];
char star;
bool isZichara;
Zichara *zich;
void copy(const PlaninarskiDom &from) {
strcpy(name, from.name);
star = from.star;
isZichara = from.isZichara;
zich = from.zich;
for(int i = 0; i < 2; i++) {
prices[i] = from.prices[i];
}
}
public:
PlaninarskiDom(const char *name = "", int prices = 0, const char star = '\0') {
strcpy(this->name, name);
this->star = star;
isZichara = 0;
zich = 0;
this->prices[0] = 0;
this->prices[1] = 0;
}
PlaninarskiDom(const char *name, int *prices, const char star) {
strcpy(this->name, name);
this->star = star;
isZichara = 0;
zich = 0;
this->prices[0] = prices[0];
this->prices[1] = prices[1];
}
PlaninarskiDom(const PlaninarskiDom &from) {
copy(from);
}
~PlaninarskiDom() {
delete [] zich;
}
PlaninarskiDom& operator = (const PlaninarskiDom &from) {
if(this == &from) return *this;
delete [] zich;
copy(from);
return *this;
}
void setZichara(Zichara &z) {
if(isZichara == 0) {
zich->copy(z);
isZichara = 1;
}
}
void operator --() {
if((int)star >= 65 && (int)star <= 70) {
++star;
if((int)star == 69) {
++star;
}
}
}
bool operator <= (char c) {
return star >= c;
}
void presmetajDnevenPrestoj(int day, int month, int &price) {
if(day < 0 || day > 31 || month < 0 || month > 12) {
throw 99;
}
else if(month >= 4 && month <= 8) {
price = prices[0];
}
else {
price = prices[1];
}
if(isZichara) {
price += zich->price;
}
}
friend ostream& operator << (ostream &, const PlaninarskiDom &);
};
ostream& operator << (ostream &os, const PlaninarskiDom &rhs) {
cout << rhs.name << " klasa:" << rhs.star << endl;
if(rhs.isZichara) {
cout << " so zichara" << endl;
}
return os;
}
int main(){
PlaninarskiDom p; //креирање на нов објект од класата планинарски дом
//во следниот дел се вчитуваат информации за планинарскиот дом
char imePlaninarskiDom[15],mestoZichara[30],klasa;
int ceni[12];
int dnevnakartaZichara;
bool daliZichara;
cin>>imePlaninarskiDom;
for (int i=0;i<2;i++) cin>>ceni[i];
cin>>klasa;
cin>>daliZichara;
//во следниот дел се внесуваат информации и за жичарата ако постои
if (daliZichara) {
cin>>mestoZichara>>dnevnakartaZichara;
PlaninarskiDom pom(imePlaninarskiDom,ceni,klasa);
Zichara r(mestoZichara,dnevnakartaZichara);
pom.setZichara(r);
p=pom;
}
else{
PlaninarskiDom *pok=new PlaninarskiDom(imePlaninarskiDom,ceni,klasa);
p=*pok;
}
//се намалува класата на планинарскиот дом за 2
--p;
--p;
int cena;
int den,mesec;
cin>>den>>mesec;
try{
p.presmetajDnevenPrestoj(den,mesec,cena); //тука се користи функцијата presmetajDnevenPrestoj
cout<<"Informacii za PlaninarskiDomot:"<<endl;
cout<<p;
if (p<='D')
cout<<"Planinarskiot dom za koj se vneseni informaciite ima klasa poniska ili ista so D\n";
cout<<"Cenata za "<<den<<"."<<mesec<<" e "<<cena; //се печати цената за дадениот ден и месец
}
catch (int){
cout<<"Mesecot ili denot e greshno vnesen!";
}
}
I ran a debugger on this code and it highlighted this:
name = new char[strlen(from.name) + 1];
This is the line of code as the line where the Seg Fault comes from.
This is an exercise for a class I have and I have to do it using dynamic memory allocation.
I've done this exact same thing many times before and there was no such error, so I have no idea why it is appearing, and I couldn't find an answer to this question on Google so far, so I apologize if somewhere out there it does exist.
Thanks everyone for the suggestions, this has been fixed!
You call this method:
void setZichara(Zichara &z) {
if(isZichara == 0) {
zich->copy(z);
isZichara = 1;
}
}
but you never allocate zich so you invoke UB calling a method on nullptr
Note: your PlaninarskiDom::copy() is incorrect as well, as you just assign pointer from another object aka shallow copy, which will lead to multiple destruction, though most probably you did not hit this issue yet. You should do deep copy instead or use std::shared_ptr is you plan to share ownership. Anyway if you are not limited by conditions using smart pointers are preferable when dealing with dynamically allocated objects. Or using special containers like std::vector or std::string which do proper memory management for you.

c++ unable to change members of array

i am really stuck on following problem:
2 classes:
class Article
{
char* _code;
char* _name;
double _price;
int _quantity;
public:
Article(char* code = "code", char * name = "name", double price = 0){
setCode(code);
setName(name);
_price = price;
_quantity = 0;
}
Article(Article & a){
setCode(a._code);
setName(a._name);
_price = a._price;
_quantity = a._quantity;
}
~Article(){
delete[] _code; _code = nullptr;
delete[] _name; _name = nullptr;
}
/*******SETTERS********/
void setCode(char* code){
int vel = strlen(code);
_code = new char[vel + 1];
strncpy_s(_code, vel + 1, code, _TRUNCATE);
}
void setName(char* name){
int vel = strlen(name);
_name = new char[vel + 1];
strncpy_s(_name, vel + 1, name, _TRUNCATE);
}
void setPrice(double c){ _price = c; }
/*******GETTERS********/
int getquantity(){ return _quantity; }
double getprice(){ return _price; }
//operator =
Article operator = (Article& a){
setName(a._name);
setCode(a._code);
_price = a._price;
_quantity = a._quantity;
return *this;
}
//operator-= decrease qnty for passed value.
bool operator-=(int v){
if (_quantity > v)
{
_quantity = _quantity - v;
return true;
}
cout << "Operacija nije moguca, stanje je manje nego vrijednsot za koju se umanjuje";
return false;
}
// operator ++ increase Qnty for 1.
Article operator++(int){
//Article A(_code, _name, _price);
this->_quantity++;
return *this;
}
//Preklopiti operator -- decrease value for 1.
Article operator--(){
if (_quantity >= 1)
{
_quantity--;
}
return *this;
}
//compare articles based on code.
bool operator==(Article & a){
if (strncmp(_code, a._code, strlen(_code)) == 0)
{
return true;
}
return false;
}
//operator <<
friend ostream & operator<<(ostream & COUT, Article & a);
};
ostream & operator<<(ostream & COUT, Article & a){
COUT << "code: " << a._code << endl << "name: " << a._name << endl << "price: " << a._price << ", Qnty: " << a._quantity << "\n ----------------------- \n\n";
return COUT;
}
class Item
{
Article _Article;
int* _quantity;
public:
Item(Article & a, int quantity) :_Article(a){
_quantity = new int(quantity);
}
Item() :_Article("StavkaR", "nameR", 0){
_quantity = new int(0);
}
Item(Item& s) :_Article(s._Article){
_quantity = new int(*s._quantity);
}
~Item(){
delete _quantity; _quantity = nullptr;
}
int getquantity(){ return *_quantity; }
void setquantity(int v) { *_quantity += v; }
Article getArticle() { return _Article; }
friend ostream & operator << (ostream & COUT, Item & obj);
};
ostream & operator << (ostream & COUT, Item & obj){
COUT << "quantity: " << *obj._quantity << endl << obj._Article;
return COUT;
}
First class is article with constructors, destructs and overloaded operators, second class ITEM is simple it holds article and quantity.
For test in main i have following code:
Article a;
Article b("code", "name", 1.5);
Article c(b);
cout << a;
cout << b;
c++;
c++;
c.setPrice(10);
cout << c;
cout << "\n ************************************** \n";
Item _stavke[100];
for (size_t i = 0; i < 3; i++)
{
_stavke[i].getArticle().setPrice(100);
cout << _stavke[i];
cout << "\n \t\t\t ---- \n";
}
First part of code where i test Article class and some of overloaded operators it works fine but second part where i have Item _stavke[100]; array i can list members of array - no problem but any invoked change is not accepted basicly code
_stavke[i].getArticle().setPrice(100);
does not do anything it seems ...
Can anyone point me where i am going wrong and why i can not change members of array?
Thank you in advance
Your getArticle() call returns _Article by value. That is, a copy of article. Your setPrice() is invoked on the copy, so it is not reflected in the original Item's article, which remains unchanged.