Here is my C++ class and code snip. Data does not gets properly loaded in objects which gives me memory access error. What can i do?
Base Class
using namespace std;
class Person;
class Person
{protected:
int ID;
string name;
string address;
long int phone;
string dob;
//char pass[25];
std::string pass;
public:
Person();
Person(int ID,string name, string address, long int phone, string dob, string pass) :
ID(ID),name(name), phone(phone),address(address),dob(dob),pass(pass)
{};
//COPY CONSTRUCTOR MUST BE CREATED INORDER TO MAKE VECTOR WORK
Person(const Person&);
virtual void showDetails() const = 0;
//MAKING THIS CLASS AN ABSTRACT CLASS
//BUNCH OF GETTERS
int getID() const;
string getName() const;
string getAddress() const;
long int getPhone() const;
string getDob() const;
string getPass() const;
void setPass(string a);
};
Here is the derived class from it :
#include<iostream>
#include"Person.h"
#ifndef CUSTOMER_H
#define CUSTOMER_H
class Customer :public Person {
private:
float balance;
protected:
public:
Customer() :Person(), balance(0) {}
Customer(int ID,std::string name,std::string address,long int phone, string dob,std::string
pass,float balance):
Person(ID,name,address,phone,dob,pass),balance(balance){};
//Customer(int ID, const char* name, const char* address, long int phone, string dob, const
char* pass, float balance) :
// Person(ID, name, address, phone, dob, pass), balance(balance) {};
//COPY CONSTRUCTOR MUST BE PROVIDED, ELSE VECTOR WONT WORK
Customer(const Customer& other) :Person(other) {
this->balance = other.balance;
}
float getBalance() const;
void showDetails() const;
// void setValues();
void deposit(float);
void withdraw(float);
};
#endif
Im having issues that data is not copied from file into vector properly : Here is the implementation of file handling:
void Controller::displayCustomers()
{
vector<Customer> custVector;
Customer cust;
fstream fin("customer.txt", ios::binary | ios::in);
while (fin.read(reinterpret_cast<char*>(&cust), sizeof(cust)));
{
custVector.push_back(cust);
}
fin.close();
cout << "ID\tNAME\tADDRESS\tPHONE\t\tDOB\tPASSWORD\tBALANCE" << endl;
for (vector<Customer>::iterator itr = custVector.begin();
itr != custVector.end(); ++itr)
{
cout << itr->getID() << "\t" << itr->getName() << "\t" << itr->getAddress() << "\t"
<< itr->getPhone() << "\t" << itr->getDob() << "\t" << itr->getPass() <<
"\t" << itr->getBalance() << endl;
}
cout << endl;
}
The constuctors runs more than data members and gives a memory access error when vector members are accessed. What should be the best practice.?
You cannot use binary I/O to directly read or write objects containing std::string. So this code is wrong.
fin.read(reinterpret_cast<char*>(&cust), sizeof(cust))
Best practise depends entirely on what you are trying to achieve. Must you use binary I/O? Can you change the class? Are you trying to get indexed access on your file?
For better advice you need to state what you are actually trying to achieve. At the moment all anyone can say it that this code is wrong.
It's possible that you just chose binary I/O because you throught it would be easiest. If that's the case then you should probably abandon it and switch to text I/O. But I'm not going to give advice based on speculation. You need to say what you are trying to do here.
ADDENDUM
I noticed this is your code
//char pass[25];
std::string pass;
If you followed through with that, and replaced all the strings in your classes then you might find that your reading and writing code started working. This is what's known as a plain old data (POD) class. POD classes can be read and written in the way you are trying to.
Note you would also have to remove any virtual functions as well, so maybe a POD class isn't such a good idea.
Related
i am facing issue which i want to create abstract class and 4 subclasses. Abstract class = Entry , and other subclasses are given in the code down.
class entry {
friend ostream &operator<<(ostream &os, const entry &obj);
private:
static constexpr char *def_info = "Undefind";
protected:
string desc;
int ID;
static int counter;
public:
entry() : entry(def_info) {}
entry(string input_s);
void setDesc(string);
string getDesc() const;
int getID() const;
virtual string getContents() const = 0;
virtual void displaying(ostream &os) const = 0;
virtual ~entry() = default;
};
int entry::counter = 0;
entry::entry(string input_s) :
desc{input_s} {
++counter;
ID = counter;
}
ostream &operator<<(ostream &os, const entry &obj) {
os << obj.getContents()<<endl;
obj.displaying(os);
return os;
}
void entry::setDesc(string input) {
desc = input;
}
string entry::getDesc() const {
return desc;
}
int entry::getID() const {
return ID;
}
//PhoneEntry extending the Entry with a phone number
class phone_entry :virtual public entry {
private:
static constexpr char *text = "Undefind";
static constexpr int def_no = 48000000000;
protected:
int phone_number;
public:
phone_entry(string input_s = text, int input = def_no) :
entry(input_s), phone_number(input) {}
virtual string getContents() const override {
ostringstream output;
output << "ID: " << ID << "\nD: " << desc << "\nPhone number : " << phone_number;
return output.str();
}
virtual ~phone_entry() = default;
};
//EmailEntry extending the Entry with an e-mail addres
class email_entry : virtual public entry {
private:
static constexpr char *def_info = "Undefind";
protected:
string email;
public:
email_entry(string des = def_info, string email_entry = def_info) :
entry(des), email{email_entry} {}
virtual string getContents() const override {
ostringstream output;
output << "ID: " << ID << "\nD: " << desc << "\nEmail : " << email;
return output.str();
}
virtual ~email_entry() = default;
};
//AddressEntry extending the Entry with an address containing a city, a street and a house number
class address_entry : virtual public entry {
private:
static constexpr char *def_info = "Undefind";
static constexpr int def_no = 0;
protected:
string city;
string street;
int house_number;
public:
address_entry(string des = def_info, string c = def_info, string s = def_info, int hn = def_no) :
entry{des}, city{c}, street{s}, house_number{hn} {}
virtual string getContents() const override {
ostringstream output;
output << "ID: " << ID << "\nD: " << desc << "\nCity: " << city << "\nStreet: " << street << "\nHouse number: "
<< house_number;
return output.str();
}
virtual ~address_entry() = default;
};
class contact_book : virtual public entry {
static constexpr char *def_info = "Undefind";
private:
map<string,entry *> contacts;
string nick_name;
public:
class error_mesg : public logic_error {
public:
error_mesg(const string message = "NULL") :
logic_error(message) {}
};
contact_book(string e = "undefind") :
entry{def_info},nick_name{e} {}
void add(string a , entry &content){
contacts.insert(make_pair(a,&content));
}
virtual void displaying(ostream &os) const override {
os << "TESTING";
}
};
I want to use contact_book class and use map container to insert the key and values to any of the subclasses like ("cool", new phone_entry("NAME",000000) by using add method that it has two parameters one for the key and other it must have connection to the other classes so i thought that using entry obj will do the job ofc i used pointer in the member because i want to use Polymorphism. also i dont have any idea how i can use the getContencts and it knows from which subclass calling. For example , he asked that the main will look like this :
ContactBook contacts(“My contacts”);
contacts.add(“Johny”, new PhoneEntry(“John Smith”, 100200300));
contacts.add(“Lisa”, new EmailEntry(“Lisa Wood”, “lisa#gmail.com”));
contacts.add(“Andy”, new AddressEntry(“Andrew Fox”, “Warsaw”, “Green St.”, 7));
cout << contacts;
//result (ordered):
//Andrew Fox: Warsaw, Green St. 7 (pos. 3)
//John Smith: phone 100200300 (pos. 1)
//Lisa Wood: e-mail lisa#gmail.com (pos. 2)
try {
cout << contacts[“Andy”].getContents() << endl;
//result:
//Andrew Fox: Warsaw, Green St. 7 (pos. 3)
can you please help me out how to implement them and get what he wants and how & will work on that adding method and new as well in main func.
You are not pretty clear about what your actual problem is – so I'll assume you have trouble getting the desired output for the entire contact book...
First, some other issues, though:
It is meaningless to let contact_book inherit from entry - the book contains entries, it is not one. It seems as if you only inherited to be able to override displaying function to be able to use the already defined operator<< for entry class. But that's a bad reason for inheriting. Instead, you should provide a separate overload of operator<< for your contact book:
std::ostream& operator(std::ostream& s, contact_book const& cb); // coming to later
Then get used to reuse code where appropriate; I assume getContents should output the same string that would be written to std::cout via operator<<. OK, then let's profit from:
std::string entry::getContents()
{
std::ostringstream s;
s << *this;
return s.str();
}
You don't need to have it virtual any more (and shouldn't).
I personally would go with a default for displaying function (that's not a very good name, though, you should prefer imperative forms 'display', perhaps even better: 'printToStream' or just 'printTo'):
void entry::printTo(std::ostream& s)
{
// output members to s
}
Then your inheriting classes could re-use it:
void phone_entry::printTo(std::ostream& s)
{
entry::printTo(s); // use parent's version first to print common data
// now append phone number to s...
}
Users should rather use operator<< instead of printTo function, though. Might be a good idea to have it protected (or even private).
Finally getting back to outputting the contact book:
std::ostream& operator(std::ostream& s, contact_book const& cb)
{
// you want to output every entry? then do so:
for(auto& e : cb.contacts)
{
s << *e.second << std::endl;
// ^^^^^^^ map entries are of type std::pair<key_type const, mapped_type>
// ^ you stored pointers, operator<< accepts reference
}
}
Again, you'd be re-using code already written.
One last note: You are mixing classic initialisation (parentheses) and uniform initialisation (braces), one time even in one single line (email_contact):
entry(des), email{email_entry}
I personally think UI in general has some valid reasoning, the way it was implemented in C++ is broken, though. There are quite a few other issues with, my 'favourite' one is:
std::vector<int> v0{7}; // gives you a vector with 7 elements, all 0!!!
// with classic initialization:
std::vector<int> v1(7); // now clear, you WANT such a vector!
std::vector<int> v2({7}); // now clear, you want initializer list
You now can follow my reasoning or not (others opt for UI nonetheless to profit from the advantages of), but whatever you decide – please do it consistently over the entire file/project!
This is my c++ homework and i dont really get what they meant by setting the values in the method read().
Question: Create a base class called Athlete that contains 2 member variables for attributes common to all professional athletes: name and annual salary. It should also contain pure virtual method, read(). The method read() is called to read data from the user for setting the values of the attributes.
Here is my header file
#ifndef ATHLETE_H
#define ATHLETE_H
#include <string>
using namespace std;
class Athlete
{
public:
Athlete();
~Athlete();
void setName(string name);
string getName() const;
void setSalary(double salary);
double getSalary() const;
virtual void display() const;
virtual void read(string name, double salary) const;
private:
string name;
double salary;
};
#endif
And my cpp
#include "Athlete.h"
#include <iostream>
Athlete::Athlete() {}
Athlete::~Athlete() {}
string Athlete::getName() const { return this->name; }
void Athlete::setName(string name) {
this->name = name;
}
double Athlete::getSalary() const {
return this->salary;
}
void Athlete::setSalary(double salary) {
this->salary = salary;
}
void Athlete::read(string name, double salary) const {
Athlete* temp = new Athlete();
temp->setName(name);
temp->setSalary(salary);
}
void Athlete::display() const {
cout << "Name: " << this->getName() << endl;
cout << "Salary: " << this->getSalary() << endl;
}
I tried to use the setter methods in read but theres an error.
I think you misread the question. It says that the read() method should read the data from the user. Usually it means read from the standard input. Afterwards, the method should set the values of the attributes for this specific athlete. Meaning, that the entered values relate to this specific object. Not for something new and temporary.
Pulling everything together is may look like the following:
void Athlete::read()
{
string name;
double salary;
std::cout << "Please enter the athlete name:";
std::cin >> name;
std::cout << "Please enter the athlete salary:";
std::cin >> salary;
setName(name);
setSalary(salary);
}
The thing you've missed is that read is supposed to be a pure virtual function. This means that you should not actually implement it, instead you should declare it as:
virtual void read(string name, double salary) = 0;
This means that the Athlete class cannot actually be instantiated (it's called an absract class), instead it will be used as a base class and derived classes would be required to override the read method. If they don't override the method they will themselves be abstract and cannot be instantiated.
You are not required to implement the read method as a method of Athlete once you declared it as pure virtual. It only need to be implemented as a method in the derived class(es).
Also as the method in the derived class is supposed to modify the object the method cannot be const declared (as shown above).
I am new to C++ and am not able to find the answer. This is the code I want to write:
#include <iostream>
using namespace std;
class Employee{
private:
string name;
string gender;
public:
void display();
void update(string);
Employee(string a, string b){
name = a;
gender = b;
};
~Employee(){};
};
void Employee::display(void){
cout << "Name: " << name << endl;
cout << "Gender: " << gender << endl;
}
void Employee::update(string a){
/*
a function that updates either the
name element or gender element
based on which element it is used by.
*/
}
int main(){
Employee employee1 ("Joe","Male");
Employee employee2 ("Jon","Male");
employee1.display();
employee2.display();
employee1.name.update("Mary"); // This is what I want to do: Same function
employee2.gender.update("Female"); // for different elements of same type
employee1.display();
employee2.display();
return 0;
}
How do I go about doing this?
I thought about function overloading but both elements are of the same type. I do not want to pass any extra values and make the code look crappy. Any ideas? Thank you.
Use setters and getters like this:
void Employee::setName(const string &a) {
this->_name = a; // validate or whatever you need to do
}
const string &Employee::name() const {
return this->_name;
}
void Employee::setGender(const string &a) {
// ....
}
Usage as one would expect
employee1.setName("Mary");
employee2.setGender("Female");
The basic_string class already implements a 'setter':
employee1.name.assign("Mary");
employee2.gender.assign("Female");
If you want to access name and gender like you have written in your question, you need to make both public, as #sop correctly pointed out.
I have a project I'm working on that's actually a school project that I did successfully a long time ago. I haven't done C++ in a while, and I'm having a bit of a problem jumping back into it, especially with pointers. My question is, if I need a get and set function like this
class Student
{
private:
char firstName[64];
char lastName[64];
public:
void setName(char *fName, char *lName);
void getName(char *fName, char *lName);
}
void Student::setName(char *fName, char *lName);
{
firstName = *fName;
lastName = *lName;
}
when try to make my getName function, I seem to be very confused as to how I'm supposed to return the names with the function returning void. I know that it doesn't really have to return it, if it sets a value to something that can be returned, but I guess i'm rusty enough with pointers that I can't seem to make this work. I've tried things that I think can't work, such as returning values, but i'm not sure what would go in this get function.
void Student::getName(char *fName, char *lName);
{
}
int main()
{
char myFirstName[64] = "John"
char myLastName[64] = "Doe"
//testing to see if it's reading the char arrays correctly.
cout << "Your Name is:" << myFirstName << " " << myLastName << endl;
Student aStudent;
aStudent.setName(myFirstName, myLastName);
//This part is where i'm confused. and i'm sure some above is confusing as well.
getStudent = aStudent.getName();
}
I thought maybe I could return the private variable via the constructor, but why would I need a get function then? I'm just redoing this old assignment to get back into c++, I've been doing more network admin stuff, and ignored this for long enough to lose my mind apparently. Thanks in advance, and let me know if you need more information, I tried to be thorough.
I've taken the liberty to convert your C-with-classes code to C++ code:
class Student
{
private:
std::string firstName;
std::string lastName;
public:
void setName(const std::string& fName, const std::string& lName);
void getName(std::string& fName, std::string& lName);
}
The getName function takes parameters by reference, so any changes to them will reflect outside the function:
void Student::setName(const std::string& fName, const std::string& lName);
{
firstName = fName;
lastName = lName;
}
void Student::getName(std::string& fName, std::string& lName);
{
fName = firstName ;
lName = lastName ;
}
int main()
{
std::string myFirstName = "John"
std::string myLastName = "Doe"
//testing to see if it's reading the char arrays correctly.
cout << "Your Name is:" << myFirstName << " " << myLastName << endl;
Student aStudent;
aStudent.setName(myFirstName, myLastName);
Here, the originally empty returnedFirstName and returnedLastName are modified inside the function:
//This part is where i'm confused. and i'm sure some above is confusing as well.
std::string returnedFirstName;
std::string returnedLastName;
aStudent.getName(returnedFirstName,returnedLastName);
}
I would suggest you to use std::string instead of char arrays.
So, your getName function should look like:
std::string Student::getName() {
return firstName + lastName;
}
Using pointers and returning void can be done too, but is more difficult. Before calling the getName function, you have to allocate an array to keep the string. you code should look like:
char firstName[100]
char lastName[100];
aStudent.getName(firstName, lastName);
And your getName should look like:
void Student::getName(char *fName, char *lName){
strcpy(fName, firstName);
strcpy(lName, lastName);
}
First option is your way to go.
You have modeled it with out parameters.
So You need to do.
char f[64];
char l[64];
aStudent.getName(f, l);
also I am confused. Is it even working at all ? You are just storing char in your Student object. which is neither a char array, not a char*
In C++ there is a std::string and we often avoid C style strings unless it is explicitly required to work with any other library.
There can be several ways to model your Student class.
class Student{
private:
std::string firstName;
std::string lastName;
public:
void setName(const std::string& fName, const std::string& lName);
std::string getName() const;
void getName(std::string& fname, std::string& lname) const;
}
std::string Student::getName() const{
return firstName+" "+lastName;
}
void Student::getName(std::string& fname, std::string& lname) const{
fname = firstName;
lname = lastName;
}
If you want both first and last name you can model it after std::pair or with boost::tuple
class Student{
public:
typedef std::pair<std::string, std::string> NamePairT
private:
NamePairT _namePair;
public:
void setName(const NamePairT& namePair);
NamePairT getName() const;
}
void Student::setName(const NamePairT& namePair) const{
_namePair = namePair;
}
NamePairT Student::getName() const{
return _namePair;
}
Student s;
s.setName(std::make_pair("Some", "One"));
Student::NamePairT name = s.getName();
std::cout << s.first << " " << s.second;
First, the "working" code:
#include <string.h>
class Student
{
private:
char firstName[64];
char lastName[64];
public:
void setName(const char *fName, const char *lName)
{
strcpy(firstName, fName);
strcpy(lastName, lName);
}
void getName(char *fName, char *lName) const
{
strcpy(fName, firstName);
strcpy(lName, lastName);
}
};
Now, why you should use std::string instead:
This code is open to buffer overflows. What if the name doesn't fit in the array allocated? For setName, this can be overcome using strncpy since the size of the available buffer is known. For getName, however, the signature your professor gave you has no information about the size of the destination buffer, so it's totally impossible to protect against writing past the end. std::string, on the other hand, both knows its buffer size and can be reallocated to store as much data as needed, so the buffer overflow can't happen.
your method returns void so getStudent = aStudent.getName(); has no meaning. If you are trying to set *fName and *lName to the values of aStudent, you could do something like this
void Student::getName( char *fName, char *lName ){
fName = firstName;
lName = lastName;
}
and set the values in main something like:
char *fName, *lName;
aStudent( fName, lName);
My code compiles fine but I am having issues with a particular section not displaying the correct output.
Here is my base class
class Item
{
protected:
//int count;
string model_name;
int item_number;
public:
Item();
Item(string name, int number);
string getName(){return model_name;}
int getNumber(){return item_number;}
and here is my derived class:
class Bed : public Item
{
private:
string frame;
string frameColour;
string mattress;
public:
Bed();
Bed(int number, string name, string frm, string fclr, string mtres);
Function definitions:
Bed::Bed(int number, string name, string frm, string fclr, string mtres)
{
model_name=name;
item_number=number;
frame=frm;
frameColour=fclr;
mattress=mtres;
cout<<model_name<<item_number<<frame<<frameColour<<mattress<<endl;
}
Main section that is causing the problem:
Item* item= new Bed(number, name, material, colour, mattress);
cout<<"working, new bed"<<endl;
v.push_back(item);
cout<<"working pushback"<<endl;
cout<<" this is whats been stored:"<<endl;
cout<<v[count]->getName<<endl;
cout<<v[count]->getNumber<<endl;
count++;
when the programme executes, the cout within the constructor shows the correct output, but when I call getname and getnumber from the main function the programme prints '1' for both , no matter what's stored in there.
I thought that derived classes could use base class methods, what have I missed?
Any help would be great
thanks
Hx
Well, you example is not related to polymorphism. The reason here is that you are not using any virtual functions. Here is the code that you can use.
class Item
{
protected:
std::string model_name;
int item_number;
public:
Item();
Item(std::string& name, int number) : model_name(name), item_number(number) {};
std::string getName(){return model_name;}
int getNumber(){return item_number;}
};
class Bed : public Item
{
private:
std::string frame;
std::string frameColour;
std::string mattress;
public:
Bed();
Bed(int number, std::string& name, std::string& frm, std::string& fclr, std::string& mtres) : Item(name, number),
frame(frm),
frameColour(fclr),
mattress(mtres) {};
};
int main()
{
int count = 0;
std::vector<Item*> v;
Item* item = new Bed(2, std::string("MyBed"), std::string("wood"), std::string("red"), std::string("soft"));
std::cout << "working, new bed" << std::endl;
v.push_back(item);
std::cout << "working pushback" << std::endl;
std::cout << " this is whats been stored:" << std::endl;
std::cout << v[count]->getName() << std::endl;
std::cout << v[count]->getNumber() << std::endl;
++count;
getchar();
}
This looks incorrect (and I am unsure how this even compiled):
cout<<v[count]->getName<<endl;
cout<<v[count]->getNumber<<endl;
as getName and getNumber are methods. Change to:
cout<<v[count]->getName()<<endl;
cout<<v[count]->getNumber()<<endl;
Additionally, the initialisation of count is not posted: ensure it is zero.
count appears to be the size of your vector. After you push back the last element, you're not incrementing count, so you're printing an older element.
Why don't you try:
cout<<v[v.size()-1]->getName<<endl;
cout<<v[v.size()-1]->getNumber<<endl;
Also, you should start using initialization lists in your constructors:
Bed::Bed(int number, string name, string frm, string fclr, string mtres) :
Item(name,number),
frame(frm),
frameColour(fclr),
mattress(mtres)
{
}
You have not called the base class's constructor from the derived class... Where as it should be the first line... update the code, I am sure it will start working..
EDIT
If it doesn't than you should probably also check the way you are handling count variable... as pointed out by others..