I'm lost with this code, what do I need to do for
Couple *pcouple1 = new Couple(mary, *pjohn);
Couple couple2(*pjane, mark);
to work? I get a red squigle between Couple(mary and couple2(*pjane with the folliwing info:
*error C2664: 'Couple::Couple(const Couple &)' : cannot convert argument 1 from 'Person' to 'const char *'
*IntelliSense: no instance of constructor "Couple::Couple" matches the argument list
argument types are: (Person, Person)
Code is:
Class Couple & Person
class Person {
char* name;
public:
friend class Couple;
friend ostream& operator<<(ostream& str, const Person& os)
{
str << os.name;
return str;
};
Person(const char* n)
{
name = (char*)n;
cout << "char constructor " << name << endl;
};
Person(const Person& os)
{
name = os.name;
cout << "Person constructor " << name << endl;
};
Person& operator=(const Person& os)
{
this->name = os.name;
return *this;
};
~Person()
{
free(name);
cout << "Class Person Destructor" << endl;
};
char* getName(){
return name;
};
};
class Couple {
Person *wife, *husband;
public:
friend ostream& operator<<(ostream& str, const Couple& p)
{
str << "He " << *p.husband << " She " << *p.wife;
};
Couple::Couple(const char* m, const char* z)
{
husband = new Person(m);
wife = new Person(z);
cout << "Couple1: " << endl;
};
Couple::Couple(const Couple& other)
{
husband = new Person(*other.husband);
wife = new Person(*other.wife);
cout << "Couple2: " << endl;
}
Couple& operator=(const Couple& other)
{
this->husband = new Person(*other.husband);
this->wife = new Person(*other.wife);
return *this;
};
~Couple()
{
free(husband->name);
free(husband);
free(wife->name);
free(wife);
cout << "Class Couple Destructor" << endl;
};
};
Main function:
int main(void) {
Person *pjohn = new Person("John"),
*pjane = new Person("Jane");
Person mary("Mary"), mark("Mark");
Couple *pcouple1 = new Couple(mary, *pjohn);
Couple couple2(*pjane, mark);
delete pjohn;
delete pjane;
cout << *pcouple1 << endl;
cout << couple2 << endl;
couple2 = *pcouple1;
delete pcouple1;
cout << couple2 << endl;
return 0;
}
Could somebody recommend me a good source/site/book/exercise to understand better function pointers similar to this exercise, thanks in advance I'm still learning.
Obviously your Couple constructor expects two char* arguments, but you are trying to construct Couple object with two Person objects. Either introduce constructor, that will accept Person as argument, or convert given Person instances to char*.
Related
I was trying to learn operator overloading in C++ PL. I made an exercise shown below. What I want to do is overload << operator for each derived class and use it on my main. But whenever I do it, its only working for Base class. What is the problem here?
Class Employee:
class Employee {
public:
string name;
int id;
int exp_level;
double salary;
Employee() {
this->name = "";
this->id = 0;
this->exp_level = 0;
this->salary = 0.0;
}
~Employee() {
//WTF
}
virtual void calculateSalary() {
//CODE
}
virtual void registerX() {
//CODE
}
friend ostream& operator<<(ostream& os, const Employee& e) {
os << e.name << " " << e.exp_level << " " << e.id << " " << e.salary << endl;
return os;
}
};
Class Technical:
class Technical : public Employee {
public:
string profession;
Technical() {
this->profession = "";
}
~Technical() {
}
virtual void calculateSalary() {
//CODE
}
virtual void registerX() {
//CODE
}
friend ostream& operator<<(ostream& os, const Technical& e) {
os << e.name << " " << e.exp_level << " " << e.id << " " << e.salary << "Technical" << endl;
return os;
}
};
Class Engineer:
class Engineer : public Employee {
public:
Engineer() {
}
~Engineer() {
}
virtual void calculateSalary() {
//CODE
}
virtual void registerX() {
//CODE
}
friend ostream& operator<<(ostream& os, const Engineer& e) {
os << e.name << " " << e.exp_level << " " << e.id << " " << e.salary << "Engineer" << endl;
return os;
}
};
Main Method:
int main()
{
Employee* e = new Employee();
Employee* t = new Technical();
Employee* ee = new Engineer();
cout << *e << endl;
cout << *t << endl;
cout << *ee << endl;
}
Output:
0 0 0
0 0 0
0 0 0
C++ chooses the best overload based on the static type's of the function arguments, and because the type is Employee in this case, the Employee's operator<< gets called.
If you want it to call the correct version when you have a static type pointer / reference to it that doesn't match it's dynamic type you'll have to use a virtual function or use dynamic_casts / typeid to check for the concrete runtime type (virtual functions are the cleanest approach imho)
Example: godbolt
class Employee {
public:
virtual ~Employee() = default;
friend std::ostream& operator<<(std::ostream& os, const Employee& e) {
return e.put(os);
}
protected:
virtual std::ostream& put(std::ostream& os) const {
os << "Employee!";
return os;
}
};
class Technical : public Employee {
protected:
std::ostream& put(std::ostream& os) const override {
os << "Technical Employee!";
return os;
}
};
class Engineer : public Employee {
protected:
std::ostream& put(std::ostream& os) const override {
os << "Engineer Employee!";
return os;
}
};
int main() {
Employee* e = new Employee();
Employee* t = new Technical();
Employee* ee = new Engineer();
std::cout << *e << std::endl;
std::cout << *t << std::endl;
std::cout << *ee << std::endl;
delete ee;
delete t;
delete e;
}
would result in:
Employee!
Technical Employee!
Engineer Employee!
Also keep in mind that once you have at least 1 virtual function in a class then the destructor should almost definitely be also virtual.
e.g.:
Employee* e = new Technical();
delete e;
would only call ~Employee(), but not ~Technical(), if the destructor is not virtual.
So whenever you want to delete an object through a pointer to one of it's base-classes the destructor needs to be virtual, otherwise it's undefined behavior.
Due to these declarations
Employee* e = new Employee();
Employee* t = new Technical();
Employee* ee = new Engineer();
the static type of the expressions *e, *t, *ee is Employee &. So the operator
friend ostream& operator<<(ostream& os, const Employee& e)
is called for all three objects.
A simple way to make the friend operator << "virtual" is to define in each class a virtual function like for example
virtual std::ostream & out( std::ostream & ) const;
and define the (only) friend operator like
friend ostream& operator<<(ostream& os, const Employee& e)
{
return e.out( os );
}
The virtual function out need to be redefined in each derived class.
I am currently learning C++, coming from C#/Java background, using visual studio 2017.
I have a question in regards to creating objects on heap and referencing them properly down the road. So far I came across multiple tutorials and ways of doing things. Some recommend using smart pointers as much as possible, others swear its the devils tool.
My current main looks like this:
//Main
Person *makePerson()
{
string name;
int age;
cout << "Input name: ";
cin >> name;
cout << "Input age: ";
cin >> age;
return new Person(name, age);
}
Child *makeChild(Person &parent)
{
return new Child(*makePerson(), &parent);;
}
int main()
{
cout << "---Input parent data---" << endl;
Person *person = makePerson();
cout << "printing: " << *person << endl;
cout << "---Input child data---" << endl;
Child *child = makeChild(*person);
cout << "printing: " << *child << endl;
cout << "---end of main---" << endl;
delete person;
delete child;
return 0;
}
A function handles input of personal data and returns a pointer to new Person object. Then I have a function that handles creation of child object by taking a parent reference and asking makePerson for remaining data.
Can this be considered good C++? How can I make it better? I would really appreciate some code examples.
As some have already suggested, I could replace raw pointers with either shared_ptr<Person> person (heavy) or unique_ptr<Person> (better than shared).
This is code for Person and child classes. Note that Child has a raw pointer of type Person *parent.
//header
class Person
{
protected:
std::string name;
int age;
public:
Person();
Person(const Person& other);
Person(std::string inName, int inAge);
~Person();
virtual void print() const;
std::string getName() const;
int getAge() const;
Person &operator=(const Person &other);
//overload print functionality, act as if it was toString
friend std::ostream &operator<<(std::ostream &out, const Person &p);
};
//cpp
Person::Person() : name(""), age(0) {
std::cout << "Person empty constructor" << std::endl;
}
Person::Person(std::string inName, int inAge) : name(inName), age(inAge) {
std::cout << "Person (" << name << ") default constructor" << std::endl;
}
Person::Person(const Person & other) : name(other.name), age(other.age) {
std::cout << "Person (" << name << ") copy constructor" << std::endl;
}
Person::~Person() {
std::cout << "Person (" << name << ") destructor" << std::endl;
}
void Person::print() const {
std::cout << name << ", " << age << std::endl;
}
std::string Person::getName() const
{
return name;
}
int Person::getAge() const
{
return age;
}
Person & Person::operator=(const Person & other) {
std::cout << "Person (" << other.name << ") assignment constructor" << std::endl;
name = other.name;
age = other.age;
return *this;
}
std::ostream &operator<<(std::ostream &out, const Person &p) {
return out << p.name << ", " << p.age;
}
A child is a person and it makes sense for a child to have knowledge of who childs parent is. However, am uncertain how to handle this "knowledge". Here is code I am using for child class:
//Header
class Child : public Person
{
private:
const Person *parent;
public:
Child();
Child(std::string name, int age);
Child(std::string name, int age, const Person *parent);
Child(const Child &child, const Person *parent);
Child(const Person &person);
~Child();
Child &operator=(const Child &other);
void print() const;
friend std::ostream &operator<<(std::ostream &out, const Child &c);
};
//cpp
Child::Child() {
std::cout << "Child empty constructor" << std::endl;
}
Child::Child(std::string name, int age) : Person(name, age), parent(nullptr) {
std::cout << "Orphan (" << name << ") constructor" << std::endl;
}
Child::Child(std::string name, int age, const Person *parent) :
Person(name, age), parent(parent) {
std::cout << "Child (" << name << ") default constructor" << std::endl;
}
Child::Child(const Child &child, const Person *parent) :
Person(child.name, child.age), parent(parent) {
std::cout << "Child (" << child.name << ") copy constructor" << std::endl;
}
Child::Child(const Person &person) : Person(person), parent(nullptr) {
std::cout << "Child from person (" << name << ") constructor" << std::endl;
}
Child::~Child() {
std::cout << "Child (" << name << ") destructor" << std::endl;
}
Child & Child::operator=(const Child & other) {
name = other.name;
age = other.age;
parent = other.parent;
std::cout << "Child (" << name << ") assignment constructor" << std::endl;
return *this;
}
void Child::print() const {
if(parent)
std::cout << *this << " is child of " << *parent << std::endl;
else
std::cout << *this << " is orphan" << std::endl;
}
std::ostream &operator<<(std::ostream &out, const Child &c) {
return out << c.name << ", " << c.age << " is " <<
(c.parent ? ("child of " + c.parent->getName() + ", " + std::to_string(c.parent->getAge())) : "orphan");
}
This is the output I get:
I suppose my question still remains, could anyone give me an example of how it should look like to be considered good C++?
#user4581301 if you take a look at the updated main, do you mean I should return a std::unique_ptrinstead of a * (raw pointer)? In which case my function will look like this:
std::unique_ptr<Person> makePerson2()
{
string name;
int age;
cout << "Input name: ";
cin >> name;
cout << "Input age: ";
cin >> age;
return std::unique_ptr<Person>(new Person(name, age));
}
And variable declaration as:
std::unique_ptr<Person> upParent = makePerson2();
cout << "printing: " << *upParent << endl;
Would this be considered "better" C++ than what I have so far?
I think that one of the most important thing to know about C++ especially if you come from Java/C# background is:
Objects are value-types by default, not reference type!
you entire code could have been written as simply:
int main()
{
//this work
Person person("John Doe", 22);
//this work
Child child("Johnny Doe", 2, person);
cout << "---end of main---" << endl;
return 0;
}
See how the code turned into nothing? you don't have to worry about allocations, deleting unused object etc. because objects are not reference type to begin with!
My personal hierarchy of rules go:
use objects as value types as much as possible. pass them by reference to avoid copies. make sure a valid move constructor is implemented for relevant classes. objects as value types + references should be the default way of programming C++.
if you can't use a reference, because you want to specify a missing object, use C-pointer. by any way, strict the C-pointers to minimum and never let them manage anything. C-pointers are basically "viewers" to something and they can view "nothing" (or null). always think if you can replace C-pointer by C++ reference. if you can do it, do it.
use std::unique_ptr if for some reason you do need dynamic memory allocation, such as dynamic polymorphism. keep in mind that C++ works mostly on templates as static polymorphism, instead of the Java style inherit+override technique.
use std::shared_ptr rarely,and only when you're sure there are many owners, like an object which is referenced on different threads. std::shared_ptr should be used in extreme cases. always copy the shared pointer. never pass the shared pointer by reference.
Anyway, new , new[] , delete and delete[] are pretty much deprecated. only library writers should use them in very extreme cases. std::make_ should be the only way allocating object on the heap, alongside the STL containers such as std::vector and std::list.
I am relatively new to classes and was introduced to copy constructors and overloading last week. I am supposed to overload the = operator and use it to assign multiple variables using the class name.
For some reason, running the program causes a popup saying
program.cpp has stopped responding.
I am positive there are minor/major things that I am missing due to me being a rookie with objects in C++.
Any advice is very much appreciated!
#include<iostream>
#include<string>
using namespace std;
class Employee
{
private:
char *name;
string ID;
double salary;
public:
Employee() {}
Employee(char *name, string eid, double salary) {}
Employee(const Employee &obj)
{
name = new char;
ID = obj.ID;
salary = obj.salary;
}
~Employee() {}
void setName(char *n)
{
name = n;
}
void setID(string i)
{
ID = i;
}
void setSalary(double s)
{
salary = s;
}
char getName()
{
return *name;
}
string getID()
{
return ID;
}
double getSalary()
{
return salary;
}
Employee operator = (Employee &right)
{
delete[] name;
ID = right.ID;
salary = right.salary;
return *this;
}
};
int main()
{
Employee e1("John", "e222", 60000), e2(e1), e3, e4;
e3 = e4 = e2;
e2.setName("Michael");
e2.setSalary(75000);
e3.setName("Aaron");
e3.setSalary(63000);
e4.setName("Peter");
cout << "\nName: " << e1.getName() << "\nID: " << e1.getID() << "\nSalary: " << e1.getSalary() << endl;
cout << "\nName: " << e2.getName() << "\nID: " << e2.getID() << "\nSalary: " << e2.getSalary() << endl;
cout << "\nName: " << e3.getName() << "\nID: " << e3.getID() << "\nSalary: " << e3.getSalary() << endl;
cout << "\nName: " << e4.getName() << "\nID: " << e4.getID() << "\nSalary: " << e4.getSalary() << endl;
return 0;
}
There are several issues with this code.
The first issue is in the constructor Employee(char *name, string eid, double salary) {} which is just doing nothing and ignoring the passed data whereas it should be using it to initialize the fields (class member data).
Employee(char *name, string eid, double salary)
{
const size_t bufferSize = strlen(name) + 1;
this->name = new char[bufferSize];
memcpy(this->name, name, bufferSize);
this->ID = eid;
this->salary = salary;
}
The second issue is in the copy constructor Employee(const Employee &obj) , where you are just initializing the name (with single byte of char) and that's it. What the copy constructor suppose to do is initialize the fields (class members) of the class with the fields of the class object being passed to it.
Employee(const Employee &obj)
{
const size_t bufferSize = strlen(name) + 1;
this->name = new char[bufferSize];
memcpy(this->name, name, bufferSize);
ID = obj.ID;
salary = obj.salary;
}
the third issue is with the default constructor which is suppose to initialize the name pointer with the NULL so that the destructor could clean it up nicely:
Employee() : name(NULL) {}
~Employee()
{
if (NULL != name)
delete[] name;
}
the fourth and last problem is with the assignment operator that's suppose to properly initialize the name member data instead of deleting it (which doesn't make sense)
Employee operator = (Employee &right)
{
if (NULL != this->name)
delete[] this->name;
const size_t bufferSize = strlen(right.name) + 1;
this->name = new char[bufferSize];
memcpy(this->name, right.name, bufferSize);
ID = right.ID;
salary = right.salary;
return *this;
}
The problem is this line:
delete[] name;
You shouldn't delete anything you haven't allocated with new first. If you delete the above line, your program kind of works. :)
Here's a slightly revised version of your program that works:
#include<iostream>
#include<string>
using namespace std;
class Employee
{
private:
char *name;
string ID;
double salary;
public:
Employee() {}
Employee(char *name, string eid, double salary)
: name (name) // ADDED THESE
, ID(eid)
, salary(salary)
{
}
Employee(const Employee &obj)
{
name = obj.name; // WAS: new char;
ID = obj.ID;
salary = obj.salary;
}
~Employee() {}
void setName(char *n)
{
name = n;
}
void setID(string i)
{
ID = i;
}
void setSalary(double s)
{
salary = s;
}
char * getName()
{
return name;
}
string getID()
{
return ID;
}
double getSalary()
{
return salary;
}
Employee operator = (const Employee &right)
{
name = right.name; // WAS: delete[] name;
ID = right.ID;
salary = right.salary;
return *this;
}
};
int main()
{
Employee e1("John", "e222", 60000), e2(e1), e3, e4;
e3 = e4 = e2;
e2.setName("Michael");
e2.setSalary(75000);
e3.setName("Aaron");
e3.setSalary(63000);
e4.setName("Peter");
cout << "\nName: " << e1.getName() << "\nID: " << e1.getID() << "\nSalary: " << e1.getSalary() << endl;
cout << "\nName: " << e2.getName() << "\nID: " << e2.getID() << "\nSalary: " << e2.getSalary() << endl;
cout << "\nName: " << e3.getName() << "\nID: " << e3.getID() << "\nSalary: " << e3.getSalary() << endl;
cout << "\nName: " << e4.getName() << "\nID: " << e4.getID() << "\nSalary: " << e4.getSalary() << endl;
return 0;
}
We are supposed to use copy-on-write on our school project. I've been experimenting with a very simple class, but without any luck. I have this:
#include <iostream>
#include <cstdlib>
#include <cstring>
using namespace std;
class CPerson {
public:
CPerson ();
CPerson (const CPerson&);
~CPerson ();
char* m_name;
char* m_surname;
int m_refs;
void rename (const char*, const char*);
};
CPerson :: CPerson () : m_name(NULL), m_surname(NULL), m_refs(1) {}
CPerson :: CPerson (const CPerson& src) : m_name (src.m_name), m_surname (src.m_surname), m_refs(src.m_refs+1) {} // supposed to be a shallow copy
CPerson :: ~CPerson () {
if (m_refs == 1) {
delete [] m_name;
delete [] m_surname;
}
else --m_refs;
}
void CPerson :: rename (const char* name, const char* surname) {
delete [] m_name;
delete [] m_surname;
m_name = new char [strlen(name)+1];
m_surname = new char [strlen(surname)+1];
strcpy (m_name, name);
strcpy (m_surname, surname);
}
int main () {
CPerson a;
a.rename ("Jack", "Smith");
cout << a.m_name << " " << a.m_surname << endl;
CPerson b(a);
cout << a.m_name << " " << a.m_surname << endl;
cout << b.m_name << " " << b.m_surname << endl;
// good so far...
a.rename ("John", "Anderson"); // should rename both 'a' and 'b'
cout << a.m_name << " " << a.m_surname << endl;
cout << b.m_name << " " << b.m_surname << endl;
// prints random values
return 0;
}
It is strange because when I take out the couts, everything works OK (no leaks, no errors by valgrind).
Any help would be appreciated.
Your design is flawed. You need to implement the reference count on the character data itself, not on the individual CPerson objects, as they are not sharing a single reference count variable with each other.
Try something more like this instead:
#include <iostream>
#include <string>
using namespace std;
struct SPersonData
{
string m_name;
string m_surname;
int m_refcnt;
SPersonData() : m_refcnt(0) {}
void incRef() { ++m_refcnt; }
void decRef() { if (--m_refcnt == 0) delete this; }
};
class CPerson
{
private:
SPersonData *m_data;
public:
CPerson ();
CPerson (const CPerson&);
~CPerson ();
CPerson& operator= (const CPerson&);
string getName() const;
string getSurname() const;
void rename (const string&, const string&);
};
CPerson::CPerson ()
: m_data(NULL) {}
CPerson::CPerson (const CPerson& src)
: m_data (src.m_data)
{
if (m_data) m_data->incRef();
}
CPerson::~CPerson ()
{
if (m_data) m_data->decRef();
}
CPerson& operator= (const CPerson &src)
{
if (this != &src)
{
if (m_data) m_data->decRef();
m_data = src.m_data;
if (m_data) m_data->incRef();
}
return *this;
}
string CPerson::getName() const
{
if (m_data) return m_data->m_name;
return string();
}
string CPerson::getSurname() const
{
if (m_data) return m_data->m_surname;
return string();
}
void CPerson::rename (const string &name, const string &surname)
{
if ((m_data) && (m_data->m_refcnt > 1))
{
m_data->decRef();
m_data = NULL;
}
if (!m_data)
{
m_data = new SPersonData;
m_data->incRef();
}
m_data->m_name = name;
m_data->m_surname = surname;
}
Which can be greatly simplified in C++11 and later by using std::shared_ptr to manage the reference count:
#include <iostream>
#include <string>
#include <memory>
using namespace std;
struct SPersonData
{
string m_name;
string m_surname;
};
class CPerson
{
public:
shared_ptr<SPersonData> m_data;
string getName() const;
string getSurname() const;
void rename (const string&, const string&);
};
string CPerson::getName() const
{
if (m_data) return m_data->m_name;
return string();
}
string CPerson::getSurname() const
{
if (m_data) return m_data->m_surname;
return string();
}
void CPerson::rename (const string &name, const string &surname)
{
if (!((m_data) && m_data.unique()))
m_data = make_shared<SPersonData>();
m_data->m_name = name;
m_data->m_surname = surname;
}
Either way, your test would then look like this:
int main ()
{
CPerson a;
a.rename ("Jack", "Smith");
cout << a.getName() << " " << a.getSurname() << endl;
CPerson b(a);
cout << a.getName() << " " << a.getSurname() << endl;
cout << b.getName() << " " << b.getSurname() << endl;
// good so far...
a.rename ("John", "Anderson"); // should rename only 'a' not 'b'
cout << a.getName() << " " << a.getSurname() << endl;
cout << b.getName() << " " << b.getSurname() << endl;
return 0;
}
Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question appears to be off-topic because it lacks sufficient information to diagnose the problem. Describe your problem in more detail or include a minimal example in the question itself.
Closed 8 years ago.
Improve this question
I'm trying to put together an assignment here and got stuck on one point. The question is to create Person class with Student derived class. Then overload both << and >> operators. In the end create checking program to create array of 20 Persons and keep loading either Person or Student. At any point we can print what we have by far - Person output is Name char*/Age int/Parents *char[2], Student output is Name char*/Age int/ID int.
My problem is with the array point - I can't figure out how to implement this and right now I'm stuck with:
Array of pointers to person
We choose if its person/student
istream to get the data
Here is main code part:
#include <iostream>
#include <conio.h>
#include "Header.h"
using namespace std;
int main()
{
char choice;
Person* Tablica[20];
Person* temp;
int i = 0;
while (1)
{
cout << "choices:" << endl;
cout << "(p)erson, (s)tudent, s(h)ow, (e)nd" << endl;
choice = _getch();
if (choice == 'h' || choice == 'H'){
for (int n = 0; n < i; n++){
cout << *Tablica[n] << endl;
}
}
if (choice == 'e' || choice == 'E'){ break; }
if (choice == 'p' || choice == 'P'){
temp = new Person;
cin >> *temp;
Tablica[i] = temp;
cout << *Tablica[i] << endl;
i++;
}
if (choice == 'S' || choice == 's'){
temp = new Student;
cin >> *temp;
Tablica[i] = temp;
cout << *Tablica[i] << endl;
i++;
}
}
system("PAUSE");
return 0;
}
I'm able to load first person/student and then code breaks without error.
So what I'm asking here is, could you look at the code and perhaps point me in the right direction?
Disclaimer: We have to use array, no vectors etc. Yes, conio.h is there as well and it has to stay... Obviously I'm beginner.
Person:
#include <iostream>
class Person
{
public:
Person();
Person(const Person&);
Person(char* n, int a, char* Parent1, char* Parent2);
char* getName();
int getAge();
char* getDad();
char* getMum();
virtual ~Person();
virtual Person operator=(const Person &);
virtual Person operator+(const Person &);
virtual Person operator+=(Person &);
virtual void write(std::ostream&);
virtual void read(std::istream&);
friend std::istream& operator>>(std::istream&, Person &);
friend std::ostream& operator<<(std::ostream&, Person &);
protected:
char* name;
int age;
char* ParentName[2];
};
class Student : public Person
{
public:
Student();
Student(const Student&);
Student(char* name, int age, int id);
virtual ~Student();
int ident();
Student operator=(const Student &);
Student operator+(const Student &);
Student operator+=(Student &);
virtual void write(std::ostream&);
virtual void read(std::istream&);
friend std::istream& operator>>(std::istream&, Student &);
friend std::ostream& operator<<(std::ostream&, Student &);
private:
int ID;
};
Class
#include "Header.h"
Person::Person(){
name = 0;
age = 0;
ParentName[0] = 0;
ParentName[1] = 0;
}
Person::Person(const Person & other)
{
name = other.name;
age = other.age;
ParentName[0] = other.ParentName[0];
ParentName[1] = other.ParentName[1];
}
Person::Person(char* n, int a, char* Parent1, char* Parent2){
name = n;
age = a;
ParentName[0] = Parent1;
ParentName[1] = Parent2;
}
Person::~Person(){}
char* Person::getName(){ return name; }
int Person::getAge(){ return age; }
char* Person::getDad(){ return ParentName[0]; }
char* Person::getMum(){ return ParentName[1]; }
Person Person::operator=(const Person & other){
name = other.name;
age = other.age;
ParentName[0] = other.ParentName[0];
ParentName[1] = other.ParentName[1];
return *this;
}
Person Person::operator+=(Person & other){
int i;
i = strlen(name) + strlen(other.name) + 4;
char * temp = new char[i];
strcpy_s(temp, i, name);
strcat_s(temp, i, " - ");
strcat_s(temp, i, other.name);
name = temp;
Person wynik(name, age, ParentName[0], ParentName[1]);
return wynik;
}
Person Person::operator+(const Person & other){
int i;
i = strlen(name) + strlen(other.name) + 4;
char * temp = new char[i];
strcpy_s(temp, i, name);
strcat_s(temp, i, " - ");
strcat_s(temp, i, other.name);
Person wynik(temp, age, ParentName[0], ParentName[1]);
return *this;
}
void Person::write(std::ostream& os)
{
os << "Osoba: name = " << this->getName() << ", wiek = " << this->getAge() << ", rodzice: " << this->getDad() << ", " << this->getMum();
}
std::ostream& operator<<(std::ostream& os, Person & other){
other.write(os);
return os;
}
void Person::read(std::istream& is)
{
char* name;
name = new char;
std::cout << "name: " << std::endl;
is >> name;
std::cout << "age: " << std::endl;
int age;
is >> age;
std::cout << "dad: " << std::endl;
char* dad;
dad = new char;
is >> dad;
std::cout << "mum: " << std::endl;
char* mum;
mum = new char;
is >> mum;
Person p(name, age, dad, mum);
*this = p;
}
std::istream & operator>>(std::istream & is, Person & os){
os.read(is);
return is;
}
Student::Student() : Person(){}
Student::Student(const Student& student) : Person(student){
ID = student.ID;
}
Student::Student(char* name, int age, int id) : Person(name, age, 0, 0){
ID = id;
}
Student::~Student(){}
Student Student::operator=(const Student & student){
Person::operator=(static_cast<Person const&>(student));
ID = student.ID;
return *this;
}
Student Student::operator+=(Student & student){
Student wynik(*this);
wynik.Person::operator=(wynik.Person::operator+=(student));
return wynik;
}
Student Student::operator+(const Student& student)
{
Person::operator+(static_cast<Person const&>(student));
return *this;
}
void Student::write(std::ostream& os)
{
os << "Student: name = " << this->getName() << ", age = " << this->getAge() << ", legitymacja: " << this->ident() << std::endl;
}
int Student::ident(){ return ID; }
std::ostream& operator<<(std::ostream& os, Student & other){
other.write(os);
return os;
}
void Student::read(std::istream& is)
{
char* name;
name = new char[20];
std::cout << "name: " << std::endl;
is >> name;
std::cout << "age: " << std::endl;
int age;
is >> age;
std::cout << "ID: " << std::endl;
int id;
is >> id;
Student s(name, age, id);
*this = s;
}
std::istream & operator>>(std::istream & is, Student & st){
st.read(is);
return is;
}
Does this compile?
Table[i] = *temp;
Table is an array of pointers to Person
temp is a pointer to Person
You are trying to put an object into an array that holds pointers. Dereferencing *temp gives you an object - you need a pointer to an object, so don't dereference it there. I would expect the compiler to complain about that... does it?
Also, check your second if statement - it says (choice == 'S' || choice == 'p'), which is probably not what you meant. Both if blocks will execute if choice == 'p'...
And in Person::read() you've only allocated a single character for name. That is likely to end badly...