I'm trying to declare a member-object in a class in C++, like so:
class bankAccount
{
public:
bankAccount(int, int, int, string, int);
private:
bankBranch homeBranch;
};
bankAccount::bankAccount(int accountNumber, int accountBalance, int homebsbnumber,
string homeaddress, int homepostcode) : homeBranch(homebsbnumber, homeaddress, homepostcode) {}
class bankBranch
{
public:
/** bankBranch(const int& bsbNumber, const string& address, const int& postCode)
{
this->bsbNumber = bsbNumber;
this->address = address;
this->postCode = postCode;
}; **/
bankBranch(int, string, int);
void setPostCode()
{
cout << "Please type in the postal code of your bankBranch: " << endl;
cin >> postCode;
}
void setBsbNumber()
{
cout << "Please type in the BSB Number of your bankBranch: " << endl;
cin >> bsbNumber;
}
void setAddress()
{
cout << "Please type in the address of your bankBranch " << endl;
cin >> address;
}
// Return methods for bsb number, address and post code
int getBsbNumber()
{
return this->bsbNumber;
}
string getAddress()
{
return this->address;
}
int getPostCode()
{
return this->postCode;
}
private:
int bsbNumber;
string address;
int postCode;
};
bankBranch::bankBranch(int bsbnum, string bankaddress, int bankpostcode) {
bsbNumber = bsbnum;
address = bankaddress;
postCode = bankpostcode;
}
I am getting these erros:
sytax error : missing ';' before identifier 'homeBranch'
missing type specifier - int assumed (confused because it is obviously an object?)
'bankAccount' : illegal member initialization: 'homebranch' is not a base or member
I have tried many things and cannot seem to fix these errors, could anyone provide me with some insight on how to properly add the member-object bankBranch homeBranch to the class bankAccount? And how to properly use initialization lists.
C++ is an (almost) single-pass, top-to-bottom language. The compiler must see the declaration of a thing before it's used. Move the definition of class bankBranch above that of class bankAccount.
Just put the definition of bankBranch before your class bankAccount. See a live example here: http://ideone.com/LuMzBt
Don't forget to include string and iostream in you code.
It isn't recognising your BankBranch as a data type.
Removing the comments might help you.
And defining the bankbranch class before the other class might also help.
Also, it is good practice to define classes in separate header files, then include them separately in all the files.
Just an advice!
Related
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.
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 used two design pattern Composite and Visitor. I have no problem with Composite.But when he began writing derived classes for input and output got some errors, solution which I did never found. Although in reality, and if everything is InputVisitor done so remained only PrintVisitor and main().
Here is my code:
UPD: I rewrite some parts of code. Now I have no erros, but it only open terminal and nothind doing...
P.S. Maybe I did not properly implement of patterns. Someone has a better idea?
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
using namespace std;
class BaseComponent {
public:
virtual void add(BaseComponent *)=0;
virtual void accept(class Visitor &)=0;
};
class Card :public BaseComponent {
public:
Card (string bookName, vector<string> authors, int year): _bookName(bookName), _authors(authors), _year(year) {}
string getBookName() const {
return _bookName;
}
vector<string> getAuthors() const {
return _authors;
}
int getYear() const {
return _year;
}
void setBookName(string bookName) {
_bookName = bookName;
}
void setAuthors(vector<string> authors) {
copy(authors.begin(), authors.end(), _authors.begin());
}
void setYear(int year) {
_year = year;
}
void add(BaseComponent *){}
void accept(class Visitor &);
private:
string _bookName;
vector<string> _authors;
int _year;
};
class Folder :public BaseComponent {
public:
Folder(): _folderName(""), _parentFolder("") {}
Folder(string parentFolder): _folderName(""), _parentFolder(parentFolder) {}
string getFolderName() const {
return _folderName;
}
string getParentName() const {
return _parentFolder;
}
vector<BaseComponent*> getSubFolders() const {
return _subFolders;
}
void setFolderName(string folderName) {
_folderName = folderName;
}
void setParentFolder(string parentFolder) {
_parentFolder = parentFolder;
}
void add(BaseComponent *component) {
_subFolders.push_back(component);
}
void accept(class Visitor &);
private:
string _folderName;
string _parentFolder;
vector<BaseComponent*> _subFolders;
};
class Visitor {
public:
virtual void visitCard(Card *)=0;
virtual void visitFolder(Folder *)=0;
};
void Card::accept(class Visitor &visitor) {
visitor.visitCard(this);
}
void Folder::accept(class Visitor &visitor) {
visitor.visitFolder(this);
}
class InputVisitor :public Visitor {
public:
InputVisitor(string file): _file(file){}
void setFile(string file) {
_file = file;
}
void visitCard(Card *){}
void visitFolder(Folder *folder){
ifstream input(_file);
string folderName;
getline(input, folderName);
folder->setFolderName(folderName);
string fileName;
while (!input.eof()) {
input >> fileName;
if (fileName == "----") {
break;
} else {
Folder *subFolder = new Folder(folderName);
InputVisitor *inputVisitor = new InputVisitor(fileName);
subFolder->accept(*inputVisitor);
folder->add(subFolder);
}
}
while (!input.eof()) {
string name, tempAuthor;
vector<string> authors;
int n, year;
input >> name;
input >> n;
for (int i = 0; i<n; ++i) {
input >> tempAuthor;
authors.push_back(tempAuthor);
}
input >> year;
Card *subBook = new Card(name, authors, year);
folder->add(subBook);
}
input.close();
}
private:
string _file;
};
class PrintVisitor :public Visitor {
public:
PrintVisitor(string outputFile): _outputFile(outputFile) {}
void setOutputFile(string outputFile) {
_outputFile = outputFile;
}
void visitFolder(Folder *folder) {
ofstream output(_outputFile);
output << folder->getFolderName() << endl << "\t";
vector<BaseComponent*> subFolders = folder->getSubFolders();
vector<BaseComponent*>::iterator it;
for (it=subFolders.begin(); it!=subFolders.end(); ++it) {
(*it)->accept(*this);
}
output.close();
}
void visitCard(Card *card) {
ofstream output(_outputFile);
output << "Book: " << card->getBookName() << endl
<< "Author(s): ";
vector<string> authors = card->getAuthors();
for (vector<string>::iterator it=authors.begin(); it!=authors.end(); ++it) {
output << *it << " ";
}
output << endl << "Year: " << card->getYear();
output.close();
}
private:
string _outputFile;
};
int main() {
Folder root;
root.accept(*(new InputVisitor("root.txt")));
root.accept(*(new PrintVisitor("output.txt")));
return 0;
}
In this code:
InputVisitor *input;
input->setFile("root.txt");
root->accept(input); //Here
InputVisitor is a *input. Your accept function takes a reference to a visitor. Change it to:
root->accept(*input); //Here
and all will be fine, aside from the typo I mentioned in the comment.
If you remove all the class in front of names for classes, the compiler will tell you when there is a misspelled class name. Otherwise, it will just treat it as "there'll be a class named Visirot at some point in the future, and I don't really care what's in it right now.
Here is the declaration of BaseComponent::accept:
virtual void accept(class Visirot &)=0;
Here is the call:
root->accept(input); //Here
Here is the declaration of input:
InputVisitor *input;
So, first, the declaration of BaseComponent::accept apparently has a typo; Visirot should probably be Visitor.
Second, accept takes a Visitor&, but it's being called with an InputVisitor*. InputVisitor is derived from Visitor, soInputVisitor*is convertible toVisitor*andInputVisitor&is convertible toVisitor&, but there is no conversion from a pointer-to-type into a reference-to-type. So either changeBaseComponent::accept` to take a pointer or change the call to pass a reference.
First problem.
Assuming the typo Visirot is fixed, then at line 152 you have
subFolders[i]->accept(this); //Here some probrem
which passes a pointer to T where a T is expected.
Just dereference that pointer:
subFolders[i]->accept(*this);
Second problem.
Applying the same fixes in the main program would be wrong:
int main() {
BaseComponent *root;
InputVisitor *input;
input->setFile("root.txt");
root->accept(*input); //Here
PrintVisitor *output;
output->setOutputFile("output.txt");
root->accept(output); //And here
return 0;
}
This dereferences uninitialized pointers, which yields Undefined Behavior.
Don't do that.
Rewrite it as e.g.
int main() {
Folder root;
InputVisitor input;
input.setFile("root.txt");
root.accept(input); //Here
PrintVisitor output;
output.setOutputFile("output.txt");
root.accept(output); //And here
}
(and possibly replace Folder with whatever concrete class you want there.)
Third problem.
At line 144 you're assigning to a stream:
_outputFile = ofstream(outputFile);
where _outputFile is a member of type ofstream, and outputFile is a string.
This uses a C++11 feature (rvalue assignment of streams) that g++ didn't implement as of version 4.7.1.
Presumably the idea is to close _outputFile and reopen it: just do that, and the code will be much more portable:
// Add failure checking:
_outputFile.close();
_outputFile.open( outputFile );
Also, more descriptive naming would be good…
General problem set in the given code.
Compiling the above yields a number of warnings about signed/unsigned comparisons and unused local variables. Fix all that. Build at highest practical warning level, -Wall with g++ and /W4 with Visual C++, and make it compile cleanly.
Logic errors & testing.
Even when it compiles cleanly, there can and usually will remain logic errors. To root out those, devise a set of exactly reproducible tests, complete with any necessary test data.
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..