im new to learning c++ and iam now in the stage of creating a class that contains a vector of a class object, with methods to add new objects and print them all out.
Here is my code so far:
BankAccount.h:
#ifndef BANKACCOUNT_H
#define BANKACCOUNT_H
#include <string>
using namespace std;
class BankAccount
{
public:
BankAccount(string C_Name,int C_Balance);
/*
void SetCustomerName(string C_Name);
String GetCustomerName();
void SetCustomerBalance(int C_Balance);
int GetCustomerBalance();
*/
int deposit(int deposit_);
int withdraw(int withdraw_);
private:
string customer_name;
int customer_balance = 0;
int Deposit = 0;
int Withdraw = 0;
};
#endif // BANKACCOUNT_H
BankAccount.cpp:
BankAccount::BankAccount(string C_Name,int C_Balance)
{
customer_name = C_Name;
customer_balance = C_Balance;
}
int BankAccount :: deposit(int deposit_){
Deposit = deposit_;
Deposit = Deposit + customer_balance;
cout << "\nDeposit Balance = " << Deposit;
customer_balance = Deposit;
return customer_balance;
}
int BankAccount :: withdraw(int withdraw_){
Withdraw = withdraw_;
Withdraw = customer_balance - Withdraw;
customer_balance = Withdraw;
cout<<"After Withdraw Balance is "<<customer_balance;
return customer_balance;
}
Bank.h
#ifndef BANK_H
#define BANK_H
#include <vector>
#include "BankAccount.h"
using namespace std;
class Bank
{
public:
//variables , lists
vector<BankAccount> newAccount;
BankAccount bk;
// constructor
Bank();
};
#endif // BANK_H
Bank.cpp:
#include "Bank.h"
#include <iostream>
#include <string>
#include <vector>
using namespace std;
Bank :: Bank()
{
string Customer_name = " ";
int Customer_balance = 0;
cout << "Add name please ";
cin >> Customer_name ;
cout << "How much balance?";
cin >> Customer_balance;
newAccount.push_back(bk(Customer_name,Customer_balance));
}
The BankAccount class is fine, the main problem is in the Bank class.
I have created the bank class to create a vectors of BankAccount , with methods that adds all the BankAccount and print them all out.
However this error keeps appearing under the constructor of Bank.cpp:
error: no matching function for call to 'BankAccount::BankAccount()'
It seems that whenever im trying to declare the class object inside the BankAccount vector , the error keeps on occuring.Can someone please explain what am i doing wrong and how to fix this?
The problem is not having a std::vector of BankAccounts. The problem is that your Bank class has a data member defined: BankAccount bk; Since you don't have any explicit constructor arguments, it tries to use the default constructor BankAccount(). There is no constructor declared, so you get a compilation error.
I suspect that you don't actually need that bk data member and should probably just remove it.
The next issue is when you try to push_back you are calling the bk object instead of constructing an object. What you want is to just have
newAccount.push_back(BankAccount(Customer_name,Customer_balance));
If you're using C++11 or greater (which it looks like you are) you can use emplace_back instead
newAccount.emplace_back(Customer_name,Customer_balance);
This would leave your Bank Account class as follows:
class Bank {
public:
std::vector<BankAccount> newAccount;
Bank();
};
Bank::Bank() {
std::string Customer_name = " ";
int Customer_balance = 0;
std::cout << "Add name please ";
std::cin >> Customer_name ;
std::cout << "How much balance?";
std::cin >> Customer_balance;
newAccount.emplace_back(Customer_name,Customer_balance);
}
You simply forgot to implement the constructor of your BankAccount class.
BankAccount::BankAccount(string C_Name,int C_Balance)
: customer_name(C_name)
, customer_balance(C_Balance)
{
// TODO;
}
As a side note, you probably want you input parameter C_name to be a const std::string& cName (using camelCase to be coherent, so a variable should never start with a capital letter, it's only used for Classes and Structs).
Usually, we use variable_ for private members (you did the opposite).
Another tip, variables should be initialized out of the body of the constructor.
EDIT:
// This is wrong
newAccount.push_back(bk(Customer_name,Customer_balance));
It should be:
// Construct a valid BankAccount object using it's constructor to fill the vector
newAccount.push_back(BankAccount(Customer_name, Customer_balance));
The variable bk is useless and needs a default constructor BankAccount::BankAccount() hence the error.
You have not defined a default constructor. When you use push_back it will try to default construct the object then copy the one you are passing in. You also default construct the member bk in Bank. You have 2 options to fix this problem.
Define a default constructor, ie. BankAccount() {
If you are in c++11 you can use vectors emplace_back routine. You will need to redesign to remove the bk member from Bank.
All objects contained by a class are constructed before the body of the constructor. In this case, your Bank object directly contains a BankAccount object, bk, which is constructed before the opening { in your Bank constructor:
Bank :: Bank()
// ... bk is initialized here....
{
You attempt to give bk some arguments later, in the call to newAccount.push_back, but it's too late; the bk object has been initialized.
To control how objects are initialized in a constructor, you must put calls to their constructors in the initialization list:
Bank :: Bank()
: bk(Customer_name,Customer_balance)
{
... but of course you haven't yet defined Customer_name or Customer_balance.
So let's back up a bit: why are you pushing an account into your Bank when you initialize the Bank? Why would an account even exist at this point? Why does Bank have bk as a member? (Why is that one account treated specially, when there's a whole vector of accounts that are also contained by the Bank?) And how are you going to add more accounts later?
So, try this: first, default-initialize the Bank:
Bank :: Bank() {}
...or, in the header (if you're using C++11 or C++14, which you should be):
Bank(void) =default;
Then, add a method for adding accounts:
Bank::addAcount(void)
{
// ... use stdin/stdout to get `customer_name` and `customer_balance`...
newAccount.emplace_back(customer_name,customer_balance);
}
(Note that you'll need to add push_back instead of emplace_back if you're not using C++11 or C++14.)
It seems that there is no standard constructor BankAccount::BankAccount() defined in your BankAccount.h.
But when you declare the standard constructor then you run in the following error
Error 1 error LNK2019: unresolved external symbol "public: __thiscall BankAccount::BankAccount(void)" (??0BankAccount##QAE#XZ) referenced in function "public: __thiscall Bank::Bank(void)" (??0Bank##QAE#XZ) [...]
Means that the member variable Bank::bk is declared but never defined.
So to compile your code successfuly I recommend to remove the declaration of the member variable bk in the class Bank. It makes no sense. Then do the following in your Bank class.
Bank::Bank()
{
string Customer_name = " ";
int Customer_balance = 0;
cout << "Add name please ";
cin >> Customer_name;
cout << "How much balance?";
cin >> Customer_balance;
BankAccount bankAccount(Customer_name, Customer_balance);
newAccount.push_back(bankAccount);
}
You will verify successfuly that the vector newAccount get filled with a new BankAccount object.
Related
This is my first question on here, so excuse me if I've formatted everything in a wrong way.
So, to get to the problem - this is s university assignment of mine. The goal is to create a class called Student, which has a few fields, and store the instances in an array of Student objects. One of the tasks is to have a static variable inside the class that keeps track of how many Student instances have been created. To clarify, I have a getData() method that asks the user for the values, and then sets the current object's values to those entered (basically just like a constructor, which makes the constructors obsolete, but they want us to do it that way for some reason). In the getData() function, the static count variable gets raised by 1, as well as in the constructors, and gets decremented in the destructor.
The issue is that for some reason, Student::amount variable sets itself to 100. Every time that i try to access it from the main() function, its 100 plus the amount of students created, so if we have created 2 students, Student::amount will be equal to 102. I've nowhere explicitly set it to that number, which also matches the size of the array, by the way.
I'm still rather new to C++, I've read and watched some material on how OOP works here, but I've barely even scratched the surface.
Sorry again if my question is badly formulated or/and badly formatted, and I hope you can help me with this!
#include <iostream>
#include <string>
using namespace std;
class Date {
...
};
class Student {
// Fields
private:
string name = "";
string PID = "";
int marks[5]{ 0 };
short course = 0;
public:
// Count of all students
static int amount;
// Getters
...
// Setters
...
// Constructors
Student(); // Default one, Student::amount gets raised by 1 there
Student(string name, string PID, int marks[5], short course);
// Destructor
~Student();
// Methods
void getData();
void display(); // Display the information of a student
};
// Array of students
Student students[100];
// Student::Count
int Student::amount; // Initializes with 0 if not explicitly initialized
void Student::getData() {
cin.ignore();
cout << "\nName: "; getline(cin, name);
cout << "PID: "; getline(cin, PID);
cout << "Marks:\n";
for (int i = 0; i < 5; i++)
{
cin >> marks[i];
}
cout << "Course: "; cin >> course;
Student::amount++;
}
Student::Student(string name, string PID, int marks[5], short course) {
this->setName(name);
this->setPID(PID);
this->setMarks(marks);
this->setCourse(course);
Student::amount++;
}
The global declaration Student students[100]; calls the default Student constructor 100 times, before main is reached. According to your comment (you don't supply the constructor implementation), that constructor increases amount by 1.
A solution here is to remove Student::amount and instead use
std::vector<Student> students;
students.size() will give you the number of students in that container. Use push_back to put students into the vector.
A very crude alternative that at least is broadly compliant with the question constraints is to remove the amount increment from the default constructor, and all other places apart from the four argument constructor.
How can I create be object array of type Book in this program.
Tried to create the object but couldnt do it.Its driving me nuts. hence I need a litle help.
#include<iostream>
#include <algorithm>
using namespace std;
class BOOK{
private:
char bookname[20];
float bookprice;
public:
void getBookDetails()
{
cout<<"Enter the Book Name:";
cin>>bookname;
cout<<"Enter the Book Price:";
cin>>bookprice;
}
void displayDetails()
{
cout<<"Book Name:"<<bookname<<endl;
cout<<"Book Price:"<<bookprice<<endl;
}
};
bool comparator(string a, string b)
{
return a<b;
}
int main()
{
int Book=5;
string sortBook[]={"sandwich","apple","banana","zombie","pear"};
std::sort(sortBook,sortBook+Book,comparator);
for(int i=0;i<Book;i++)
{
cout<<sortBook[i]<<" ";
}
}
}
An object array of books would look like this:
int size = 5;
BOOK bookArray[size];
Major Problems
You are not using constructors
You are unnecessarily using char arrays
The string array 'sortBooks' should be a BOOK array (I assume?)
You declared a string array without including the string header file (probably the reason your code won't compile)
In my honest opinion, it seems that you are trying to solve a complex task without first mastering the basics of the language. I would highly recommend watching/reading a complete C++ tutorial, such as The Cherno's C++ Guide or NeuralNine's C++ Guide. Reading TutorialPoint's guides on C++ and The C++ Standard Library would also be helpful. Finally, if I had to recommend something more, I would recommend Sam's Teach Yourself C++, which helps you understand that language on a deeper level and covers many intricacies of the C++ language that beginners often overlook (note: I would not recommend using this book by itself, as it can be dry and difficult at times).
The reason your code isn't doing what you want is because you are not declaring an array of type BOOK, but of type string. Once you change the array to type book, you will run into two main problems:
Declaring an array of objects requires a default constructor.
Comparing classes requires operator overloading
Here is a good reference for learning about constructors. Essentially, a constructor is a special function that shares the exact same name as the class. When the class is declared, the constructor is automatically called. You should use a constructor to initialize the values instead of using the getBookDetails() function. If you used a constructor, you would just be able to write BOOK newBookObject("name", price)
Concerns
You are trying to sort an array of objects, which is difficult because objects are custom types, so the computer doesn't know how to compare two objects with a < (less than sign). Because of this, you would have to manually define how to compare the two objects (via operator overloading).
What You Need To Do:
Include the '<string>' Header File
Add #include <string> to the top of the file.
Change 'char bookname[20]' to 'string bookname'
I would not recommend using char arrays with classes, as it is difficult for a beginner. I agree with this question in that there's no reason to not using a string here, especially when you've already included the string library for the 'sortBooks' array you have at the bottom.
Add a Default Constructor
A default constructor is necessary to declare an array of objects.
BOOK()
{
bookname = ""
bookprice = 0.0
}
Add a Parameterized Constructor
A parameterized constuctor will allow you to declare a BOOK object like this:
BOOK newBook("book name here", price)
An Example:
BOOK newBook("Pride and Prejudice", 50.00)
BOOK(string book_name, double book_price)
{
bookname = book_name;
bookprice = book_price;
}
You can have two methods of the same name, as long as they have different parameters; this is called method overloading
Change the 'sortBooks' array to type BOOK
BOOK bookArray[5] { book1(title, price), book2(title, price) book3(title, price) book4(title, price) book5(title, price) };
Replace 'title' and 'price' with the appropriate titles and prices
Overload the '<' Operator
Comparing by Book Name
bool operator < (BOOK& otherBook)
{
return bookname < otherBook.bookname;
}
Comparing by Price
bool operator < (const BOOK& otherBook)
{
return bookprice < otherBook.bookprice;
}
Just some nitpicks/extra advice:
You don't have to name the data members 'bookname' and 'bookprice'. Since it's already in the context of a class, you could just write 'name' and 'price'.
As a beginner, you should always use doubles instead of floats, since floats have the possibility of introducing rounding errors.
Name classes using PascalCase
Finally, my code
I compiled this code on an Ubuntu Linux Subsystem using G++ (version: 9.3.0)
#include <iostream>
#include <string> //Include the 'string' header
#include <algorithm>
using namespace std;
class BOOK
{
//Private data members
private:
string bookname;
float bookprice;
//Public methods
public:
BOOK()
{
bookname;
bookprice = 0.0;
}
BOOK(string name, double price)
{
bookname = name;
bookprice = price;
}
void getBookDetails()
{
cout << "Enter the Book Name: ";
cin >> bookname;
//Add a 'cout << endl;' here
cout << "Enter the Book Price: ";
cin >> bookprice;
//Add a 'cout << endl;' here
}
void displayDetails()
{
cout << "Book Name: " << bookname << endl;
cout << "Book Price: " << bookprice << endl;
}
bool operator < (BOOK& otherBook)
{
return bookname < otherBook.bookname; //You can access private data members within the same class
}
};
int main()
{
int size = 5;
BOOK bookArray[5]; //an array of 5 'BOOK' objects
if (bookArray[0] < bookArray[1]) //Both have the same value, "" (the default value)
cout << "Item 1 is greater" << endl;
return 0;
}
I am trying to build a vending machine program with 3 different classes but I am stuck on the second portion of it. Basically the first class is the snack class, which takes 3 parameters (calories, name and price.) However, the second class VendSlot, should have two members, a snack (which I presume to be the object from the first files) and the quantity of snacks. I am really struggling to understand how to process the snack object within the second class though. How exactly do I pass the first snack object into my VendSlot class so that I can increase/decrease the amount in my storage in VendSlot and then let the user buy it when I reach the third item? I can't use pointers yet but can pass by reference and I am wondering if this is an effective way? The third class will be a vending machine that will have vendSlots and will take money to buy the items. Thank you for the help and let me know if you need clarification on the project!
This is my Snack header file
#ifndef SNACK_CPP
#include <string>
using std::string;
class Snack
{
private:
string nameOfSnack;
double snackPrice;
int numOfCalories;
public:
Snack(); //default constructor
Snack(string, double, int); //overload constructor
~Snack(); //destructor
//Accessor functions
string getNameOfSnack(); //returns name of snack
double getSnackPrice(); //returns the price of the snack
int getNumOfCalories(); //returns number of calories of snack
};
#endif // !SNACK_CPP
This is my snack.cpp file with constructors
#include "Snack.hpp"
#include <iostream>
#include <string>
using std::endl;
using std::string;
using std::cout;
using std::cin;
Snack::Snack() //default constructor
{
nameOfSnack = "bottled water";
snackPrice = 1.75;
numOfCalories = 0;
}
Snack::Snack(string name, double price, int cals)
{
nameOfSnack = name;
snackPrice = price;
numOfCalories = cals;
}
Snack::~Snack()
{
}
string Snack::getNameOfSnack()
{
return nameOfSnack;
}
double Snack::getSnackPrice()
{
return snackPrice;
}
int Snack::getNumOfCalories()
{
return numOfCalories;
}
Here is my VendSlot header file
#ifndef VENDSLOT_CPP
#include "Snack.h"
#include <string>
class VendSlot
{
public:
VendSlot(); //default constructor
VendSlot(string, double); //overload constructor
string getSnack(); //get snack name
int getAmount(); //get amount of snacks available
void decrementAmount(int); //function to decrease storage in vending machine by 1.
Snack snack; //passes snack object? I am confused what this should be.
~VendSlot(); //destructor
private:
double numOfSnacks; // number of snacks
};
#endif // !VENDSLOT_CPP
And here is my VendSlot.cpp file which I am struggling with
#include "VendSlot.h"
#include "Snack.h"
#include <iostream>
#include <string>
using std::cout;
using std::cin;
using std::endl;
using std::string;
VendSlot::VendSlot()
{
snack;
numOfSnacks = 5;
}
VendSlot::VendSlot(string Snack, double Quantity)
{
snack = Snack;
numOfSnacks = Quantity;
}
int VendSlot::getAmount()
{
return numOfSnacks;
}
string VendSlot::getSnack()
{
return snack;
}
VendSlot::~VendSlot()
{
}
I'm not sure if this is the point of your program or assignment. I'm answering your question of how does the Snack class get its constructor params when it is contained within VendSlot class.
The members contained in another class get their constructor parameters from the initialization list.
Here is an example for your case of how it could be done:
Snack::Snack(string name, double price, int cals) :
nameOfSnack(name),
snackPrice(price),
numOfCalories(cals)
{
}
VendSlot::VendSlot(Snack& snack, int quantity) :
snack(snack),
numOfSnacks(quantity)
{
}
Also, note using a reference is what would normally be used when passing in an entire class or struct. This also means the default Snack copy constructor provided by the compiler will be used unless you implement one yourself. If the class only has simple native types it should work, but to be safe you should implement it yourself.
The member quantity would seem to be best be an int type as you wouldn't have fractions of a snack being sold.
Here's the assignment operator and copy constructor defined as you'll need it.
Snack& Snack::operator=(const Snack& snack)
{
this->nameOfSnack = snack.name;
this->snackPrice = snack.price;
this->numOfCalories = snack.cals;
}
Snack::Snack(const Snack& snack)
{
*this = snack;
}
When you work with classes in C++, imagine them as variables that contain variables. So use them the same way as you use variables.
When you call an instance of a class (or "declare the variables") the constructor is called. There are two ways on doing this. With or without parameters:
Snack A("Chocolate", 12.5, 199);//This will call the constructor with parameters
Snack B;//This will call the constructor without parameters
So now we have two objects of the same class. To use the memebers of the objects we just use a period.
cout << A.getNameOfSnack() << endl;//Output: Chocolate
cout << B.getNameOfSnack() << endl;//Output: bottled water
Also, keep in mind that we can access to the public members only.
Moving on, creating an instace of a class as a member of other class is not different.
class VendSlot {
public:
Snack snack;
int numOfSnacks;
VendSlot();
VendSlot(string, double);
~VendSlot();
};
VendSlot::VendSlot() {
snack = Snack();//Call the constructor to create the object
numOfSnacks = 5;
}
VendSlot::VendSlot(string nameSnack, double Quantity) {//Notice that I changed the name of the first parameter
snack = Snack(nameSnack, 0, 0);//Call the constructor to create the object
numOfSnacks = Quantity;
}
First, you need to be sure that you are not using the name of the class as the name of a variable (that will give you errors, so be careful with that). Now, since the only data you recive in the VendSlot constructor is the name of the snack, there is no more information to send as parameter to the constructor of Snack. You can either add more parameters on the VendSlot constructor or put default values.
Since the variables nameOfSnack, snackPrice and numOfCalories are private members of their class we can't change their values from outside the class Snack.
Within the class VendSlot (or where you create the instance of the class) you can only call the functions getNameOfSnack, getSnackPrice and getNumOfCalories, which are public members of Snack.
So, implying that the function VendSlot::getSnack returns the name of the snack, the function will be as following.
string VendSlot::getSnack() {
return snack.getNameOfSnack();
}
I hope this answers your question.
I'm trying to learn how to access a constructor using array/pointers.
I know how to access class member function, but I'm stuck at how to access the constructor.
This program:
1. Ask for amount of school.
2. Ask for name of school.
3. Display each school name.
#include<iostream>
#include<string>
using namespace std;
class School
{
public:
School(string name = "")
{ schoolname = name;}
void Display()
{ cout << "School name is " << schoolname;}
private:
string schoolname;
};
int main()
{
string sname;
int schoolNO;
School *myschool;
myschool[10];
cout << "Enter number of school : ";
cin >> schoolNO;
for (int i = 0; i < schoolNO; i++)
{
cout << "Enter school name : ";
cin >> sname;
myschool[i] = new School(sname);*//The error stated is in this line...*
myschool[i].Display();
}
}
The problem is mySchool is an array of objects, not of pointers, so you cannot assign a pointer to an element of it using new.
Replace this:
School *myschool;
myschool[10];
For this:
School* myschool[10];
Now you have an array of pointers, and the new will work.
Your error has nothing to do with constructors. It has to do with incorrect declaration of your variable mySchool
What you are doing to setup your array isn't valid. You want an array of size 10 of pointers to School objects. You created myschool as a pointer to a school. Additionally myschool[10]; has no effect.
So you need to change your declaration of School *myschool to School *myschools[10]; You should also delete the bad statement I mentioned above.
Further, it is heavily suggested to choose names that reference the multiplicity of the object it models. myschool isn't being used to point or store a single school; it's a container for multiple objects. Consider naming to be schools or myschools to make it clear to someone using it what the multiplicity of the object is.
Can I initiate a string array and pass it as a function that initializes it. I know this sounds redundant, but basically I want to initiate a string array and then pass it to a variable so that I can use it later? Something like this:
This is the .h:
class ScreenBasics{
void setupAnswers(int &_numberOfAnswers, string *_answersText);
string *answersText;
{
This will be the implementation .cpp
void ScreenBasics::setupAnswers(int &_numberOfAnswers, string *_answersText){
answersText = _answersText; // this is where I get confused cause I don't know if I should initiate my string pointer using new like answersText = new string(_numberOfAnswers);
{
so in the main.cpp I can do something like this:
int main( ) {
ScreenBasics basics;
int numberOfAnswers = 4;
string newAnswers [] = { "Good", "Superb", "Great", "Perfect"};
basics.setupAnswers(numberOfAnswers, newAnswers);
// let's say I want to call some of those answers later
for ( int i = 0; i < numberOfAnswers; i++){
cout << basics.answersText[i] << endl;
}
}
Thanks!
Have you thougt about using structs? Both classes and structs can have a mixture of public and private members, can use inheritance, and can have member functions. I would recommend using structs as plain-old-data structures without any class-like features, and using classes as aggregate data structures with private data and member functions.
Your code would look like the following:
#include <iostream>
#include <string>
#include <sstream>
using namespace std;
struct movies_t {
string title;
int year;
} mine, yours;
int main ()
{
string mystr;
mine.title = "2001 A Space Odyssey";
mine.year = 1968;
cout << "Enter title: ";
getline (cin,yours.title);
cout << "Enter year: ";
getline (cin,mystr);
stringstream(mystr) >> yours.year;
cout << "My favorite movie is:\n ";
printmovie (mine);
cout << "And yours is:\n ";
printmovie (yours);
return 0;
}
void printmovie (movies_t movie)
{
cout << movie.title;
cout << " (" << movie.year << ")\n";
}
Please let me know if you have any questions!
It sounds like your class should use a constructor to initialize the pointer.
class ScreenBasics
{
ScreenBasics(std::string* _answersText, std::size_t size)
: answersText(new std::string[size])
{
// copy values from _answersText to answersText
}
};
Note that since you are allocating a resource dynamically, you will need to implement The Rule of Three: that is, you need to create a copy-constructor, copy-assignment operator and destructor. This is because their default implementations do not semantocally conform to our requirements. For instance, the default copy-constructor and copy-assignment operator perform shallow copies (that is, they copy the pointer but not what it points to). Also, the destructor doesn't free the memory allocated my new[]. You will need to provide your own definition of the destructor that calls delete[].
Fortunately, all this can be avoided by using the standard library container std::vector, which is a dynamic array class that handles the memory allocation for you. The default implementations of the aforementioned constructors will correctly copy/copy-assign a vector if the need be:
class ScreenBasics
{
ScreenBasics(std:vector<std::string> _answersText)
: answersText(_answersText)
{
}
};
Notice that the size also didn't have to be passed as a parameter. A vector maintains its size internally.