vector as with class objects in another class - c++

I can start wit hsaying that I'm kind of new to programming.
I got an assigment to create first a class bank account that holds one singel bank account, and also a class Bank that holds all bankaccounts in a vector or array.
One method that had to be included was that it should print out all the accounts in a specific Bank vector.
What I don't understand is what arguments I should pass in to such a method and also how do I call it from the main function where the vector is created.
This is what I've got so far:
void skriv_kontolista(vector <Konto>& nyttKonto)
{
for (unsigned int i = 0; i < nyttKonto.size(); i++)
{
cout << "Konto: " << i << endl;
cout << "Innehavarens kontonummer: " << nyttKonto[i].nummer << endl;
cout << "Innehavarens namn: " << nyttKonto[i].innehavare << endl;
cout << "Innehavarens saldo: " << nyttKonto[i].saldo << endl;
cout << "Innehavarens r\x84ntesats: " << nyttKonto[i].rantesats << endl;
}
}
Is that the right way to do it, and if so, how do I call this method from my main function?
Sorry if my english is bad, it's not my native language.
Thanks in advance.

The code looks OK; it should work. However, this
One method that had to be included was that it should print out all
the accounts in a specific Bank vector.
leads me to believe that skriv_kontolista should be a method in class Bank. Your skriv_kontolista function looks like it's not a method in class Bank (but I don't know for sure).
If indeed it should be a method of class Bank, you should have it in your code like this:
class Bank
{
...
void skriv_kontolista(vector <Konto>& nyttKonto)
{
...
}
...
}
In addition, a method has access to all the fields of the class. One of the fields is the vector that the method must print, so there is no need to send it as a parameter to the function!
class Bank
{
void skriv_kontolista() // no need to have any parameters
{
...
cout << "Innehavarens namn: " << nyttKonto[i].innehavare << endl;
...
}
vector <Konto>& nyttKonto; // a field of the class
}
How to call it from the main function:
int main()
{
Bank bank1, bank2, bank3;
...
bank1.skriv_kontolista();
bank2.skriv_kontolista();
bank3.skriv_kontolista();
}

Related

show class' objects using other function than main(), but called in main();

Hello I work on a project for university which has to contain classes.
I can't paste them here because it would take a lot to read hundreds of rows, but I have a class USER which works perfectly, but I also have a MainMenu() function written right before main(),which is the only one I call in main(), made with switch, which is supposed to redirect the console to classes' submenus or to show objects for every class, it depends on class.
Ok, from this MainMenu when I choose to go to Users List option, I want the console to show me the list of users, that means, all user class objects I created in main(). I thought of creating a new function with reference to class, but I don't know how to use it in this situation when I don't call it in main, and however i need to reffer to all objects in that class not to mention a specific object..
How can I do this because I only call that MainMenu() in main(), not write it here to be able to use the objects directly?
Be kind to me, I'm a beginner and I never dealt with this type of requisites. I would be grateful if you could help me solve this.
Have a nice day.
#include<iostream>
using namespace std;
class user{};
class B{};
class C{};
void MainMenu()
{
cout << " Main Menu" << endl;
cout << endl;
int chosenoption;
cout << "1.Users List" << endl;
cout << "2.Class B Submenu" << endl;
cout << "3.Class C submenu" << endl;
cout << "Type here the number of the option you want to choose: ";
cin >> chosenoption;
system("pause");
switch (chosenoption)
{
case 1:
system("cls");
cout << "There should be shown the list of users, here the only users i created in main are u1 and u2, and i need to make them and their attributes appear in this screen" << endl;
break;
case 2:
system("cls");
ClassBSubmenu();
break;
case 3:
system("cls");
ClassCSubMenu();
break;
default:
cout << endl;
cout << "Choose one of the available options only!" << endl;
cout << "Type here: " << endl;
}
}
void main()
{
User u1(...);
User u2(..);
}
ClassBSubmenu and ClassCSubmenu are functions created before MainMenu, but I haven't edited them too much
You might want to have an array of Users which you pass to the MainMenu() function.
User u[] = { User(...), User(..) };
When you pass an array, you are actually passing a pointer to the first element in the array, so the Users could be modified in MainMenu() and the changes would exist in main().
void MainMenu( User users[] )
{
...
users[0]
MainMenu( u );

Using a map that has a abstract base class pointer and calling a derived class function

I've searched on the web and can't find any solutions to my problem I hope you can help.
So I have constructed an abstract base class and have two derived classes that represents different experiments. (one is actually a derived derived class of my base class) And I made a map as such in a separate header file to store different types of experiments.
//Map class template to store name of experiment and the experiment within a project
typedef map <string, baseData <double>*> ExpContainer;
void search(string searchName, ExpContainer exps) {
ExpContainer::iterator Iter;
Iter = exps.find(searchName); //finds the entry corresponding to searchName and returns the iterator
if (Iter != exps.end()) { //need this as if entry is not found, the return will be end iter.
cout << "Found the experiment " << Iter->first << "." << endl;
Iter->second->print();
}
else {
cout << "Sorry, experiment " << searchName << " is not found" << endl;
}
}
The print() function is different for each experiment type and I know there's a problem called slicing so I've made sure that print() is virtual in the base class. Here's my base class:
namespace mynmsp {
//base class of data can be measurements or errors
template < class T> class baseData {
public:
virtual void print() =0;
virtual ~baseData() {
cout << "Destructor called for the base class." << endl;
}
};
}
Then in my main.cpp I've constructed different types of experiment and I want to print them. Each experiment class has different implementation of the print function that overrides the print function from the base class, like:
void print(){ //do something };
And in my main.cpp I have the map defined as:
ExpContainer project;
And after I have constructed each experiment, I've asked the user for the name of the experiment (expName) and inserted into project as such:
project[expName] = &expC;
I think the insertion is fine as I tested the size of project and it was correct.
However, a runtime error occured when my search function was called like this:
search(name, project);
I don't know if there's a problem with slicing or with my pointers?
I tried to make print() a virtual function in each derived class but that doesn't seem to work either.
Apologies for the long question, please help!
Edit: I've constructed my experiments inside a do while loop while project is declared outside. The whole code is very long but its basics is something like this:
string repeatstr; //user input whether to repeat do while loop or not
bool repeat = true; //condition for staying inside do while loop
ExpContainer project; //declared project to store experiments
do {
string expName;
string ans1; //character to store user input
cout << "What is the name of your experiment? " << endl;
cin >> expName;
cout << "Is this a experiment C ? (y/n)" << endl;
cin >> ans1;
if(ans1 =="y"){
//call the constructor for expC
project[expName] = &expC;
}else {
//call the constructor for expB
project[expName] = &expB;
}
cout << "Do you want to enter another experiment? (y/n)" << endl;
cin >> repeatstr;
if (repeatstr == "n") { repeat = false; }
}while (repeat); //loop over this do-while loop while repeat is true
cout << "There are " << project.size() << " in this database." << endl;
//to retrieve info from a certain experiment
string input, name;
cout << "Would you like to retrieve any experiments (y/n)? " << endl;
input = EitherInput("y", "n");
if (input == "y") {
cout << "Please enter the name of the experiment you want to retrieve: " << endl;
cin >> name;
search(name, project); //code breaks down here!
}
You are saving a pointer to the object that was already destroyed. You can check the addresses that you have in the map, most probably they are the same. You should store your experiment object in dynamic memory
if(ans1 =="y")
{
project[expName] = new expC();
} // Scope ends here and all variable created in it will be destroyed.
else
{
project[expName] = new expB();
} // Scope ends here and all variable created in it will be destroyed.
And after you are done with them you need to call delete on each pointer to avoid memory leak. Also you need to check if the items in the map are already existing, otherwise you will loose pointers to allocated memory which is automatically a memory leak.
I would recommend you to use std::share_ptr< baseData<double> > instead of bare baseData<double>*. Here you can read more about it. And also consider using typedef in order to have more clear syntax.
P.S.
The function
void search(string searchName, ExpContainer exps)
will copy whole map to its body. Use constant reference instead
void search(string searchName, const ExpContainer& exps)
But then you'll also need to declare function print as const:
virtual void print() const = 0;
and override it with const modifier:
virtual void print() const override;
And use constant iterator ExpContainer::const_iterator Iter

Reiterating through class vectors C++

I am still wrapping my head around classes and am still new to C++. My assignment is:
Create three small classes unrelated by inheritance - classes
Building, Car and Bicycle. Give each class some unique appropriate
attributes and behaviors that it does not have in common with other
classes.
Write an abstract class CarbonFootprint with only a pure virtual
getCarbonFootprint method.
Have each of your classes inherit from that abstract class and
implement the getCarbonFootprint method to calculate an appropriate
carbon footprint for that class (check out a few websites that explain
how to calculate carbon footprints).
Write an application that creates objects of each of the three
classes, places pointers to those objects in a vector of
CarbonFootprint pointers, then iterates through the vector,
polymorphically invoking each object's getCarbonFootprint method.
For each object, print some identifying information and the object's
carbon footprint.
I am having trouble trying to figure out how to iterate through my vector <CarbonFootPrint>. I also do not know if the objects being created are actually being put into this vector. My code so far is:
#include <iostream>
#include <vector>
using namespace std;
class CarbonFootPrint
{
//class declarations
public:
virtual double getCarbonFootPrint();
};
//class implementation
double CarbonFootPrint::getCarbonFootPrint()
{
return 0;
}
class Building : CarbonFootPrint
{
//class declarations
public:
Building(double e = 0, int m = 12); //constructor
~Building(); //destructor
double setElectric();
virtual double getCarbonFootPrint();
private:
double electric;
int months;
};
//class implementation
Building::Building(double e, int m)
{
electric = e;
months = m;
}
Building::~Building()
{
}
double Building::setElectric()
{
cout << "Enter your monthly electric in KWH: " << endl;
cin >> electric;
return electric;
}
double Building::getCarbonFootPrint()
{
//I would like to print out the variable information for each object created
//and then
cout << "The carbon footprint for this house is " << endl;
//when it iterates through the vector.
return(electric * months);
}
class Car : CarbonFootPrint
{
public:
Car(double = 0, double = 0); //constructor
~Car(); //destructor
double setYearlyMiles();
double setAverageMPG();
virtual double getCarbonFootPrint();
private:
double yearlyMiles, averageMPG;
int co2 = 9;
};
//class implementation
Car::Car(double ym, double mpg)
{
yearlyMiles = ym;
averageMPG = mpg;
}
Car::~Car()
{
}
double Car::setYearlyMiles()
{
cout << "Enter in your yearly miles: " << endl;
cin >> yearlyMiles;
return yearlyMiles;
}
double Car::setAverageMPG()
{
cout << "Enter in your average miles per gallon: " << endl;
cin >> averageMPG;
return averageMPG;
}
double Car::getCarbonFootPrint()
{
//I would like to print out the variable information for each object created
//and then
cout << "The carbon footprint for this car is " << endl;
//when it iterates through the vector.
return((yearlyMiles * averageMPG) * co2);
}
class Bicycle : CarbonFootPrint
{
public:
Bicycle(double = 0, int = 34); //constructor
~Bicycle(); //destructor
double setMiles();
virtual double getCarbonFootPrint();
private:
int calories;
double miles;
};
//class implementation
Bicycle::Bicycle(double m, int c)
{
miles = m;
calories = c;
}
Bicycle::~Bicycle()
{
}
double Bicycle::setMiles()
{
cout << "Enter in number of miles: " << endl;
cin >> miles;
return miles;
}
double Bicycle::getCarbonFootPrint()
{
//I would like to print out the variable information for each object created
//and then
cout << "The carbon footprint for this bicycle is " << endl;
//when it iterates through the vector.
return (miles * calories);
}
Here is my main program:
int main()
{
vector <CarbonFootPrint> *list;
int answer, i;
cout << "Welcome to the Carbon Footprint Calculator!\n" << endl;
do
{
cout << "Main Menu\n" << endl;
cout << "1: Set house info.\n" << endl;
cout << "2: Set car info.\n" << endl;
cout << "3: Set bicycle info.\n" << endl;
cout << "4: Get carbon footprint for all items set.\n" << endl;
cin >> answer;
switch (answer)
{
case 1:
{
cout << "\n" << endl;
Building *anotherBuilding;
anotherBuilding = new Building;
anotherBuilding->setElectric();
cout << "\n" << endl;
break;
}
case 2:
{
cout << "\n" << endl;
Car *anotherCar;
anotherCar = new Car;
anotherCar->setYearlyMiles();
anotherCar->setAverageMPG();
cout << "\n" << endl;
break;
}
case 3:
{
cout << "\n" << endl;
Bicycle *anotherbike;
anotherbike = new Bicycle;
anotherbike->setMiles();
cout << "\n" << endl;
break;
}
case 4:
{
//have it iterate through the vector and print out each carbon footprint.
break;
}
default:
{
cout << answer << " is not a valid option" << endl;
break;
}
}
}
while (answer != 4);
system("pause");
return 0;
}
Any help or guidance is greatly appreciated! Thank you for your time!
Re: your comments on R Sahu's post (I'm too new to be allowed to comment on other posts)
You cannot access the base class because it has defaulted to private,
class Building : CarbonFootPrint
class Car : CarbonFootPrint
class Bicycle : CarbonFootPrint
are all inheriting from CarbonFootPrint privately, which represents a "has-a" relationship, in this case although semantically a car has-a carbon foot print you're actually trying to make an "is-a" relationship, as these are all objects that implement the base class, possibly a better name for CarbonFootPrint could be CarbonFootPrintProducer.
The fix here is simply make them all publically inherited
class Name : public Base
You missed a crucial thing from:
Write an application that creates objects of each of the three classes, places pointers to those objects in a vector of CarbonFootprint pointers, then iterates through the vector, polymorphically invoking each object's getCarbonFootprint method.
Instead of
vector <CarbonFootPrint> *list; // Pointer to a vector of CarbonFootPrint objects.
You need to use
vector <CarbonFootPrint*> list; // A vector of CarbonFootPrint pointers.
Instead of
{
cout << "\n" << endl;
Building *anotherBuilding;
anotherBuilding = new Building;
anotherBuilding->setElectric();
cout << "\n" << endl;
break;
}
Use
{
cout << "\n" << endl;
Building *anotherBuilding;
anotherBuilding = new Building;
anotherBuilding->setElectric();
// Add the pointer to the list of pointers.
list.push_back(anotherBuilding);
cout << "\n" << endl;
break;
}
Make similar changes to the other object types.
At the end, call CarbonFootPrint() on the objects:
for (auto item : list )
{
item->CarbonFootPrint();
}
and delete the objects:
for (auto item : list )
{
delete item;
}
R Sahu covered almost all of it, the only bit I see remaining is;
Write an abstract class CarbonFootprint with only a pure virtual getCarbonFootprint method.
to which your class is not abstract as the function is not pure virtual, to do this simply add = 0
virtual double getCarbonFootPrint() = 0;
Pure virtual functions are ones that don't count as implemented, any class containing a pure virtual function is called "abstract" and cannot be instantiated. In this case it would have helped you identify your vector of CarbonFootPrint rather than CarbonFootPrint* to them, as the instantiations would be picked up by the compiler, although knowing template compiler errors you'd have had a couple hundred lines of error message for this simple mistake.
For full disclosure: a pure virtual function can actually be defined, e.g.;
virtual double getCarbonFootPrint() = 0;
double CarbonFootPrint::getCarbonFootPrint()
{
// some code
return 0;
}
which can then be called from any derived class
double Building::getCarbonFootPrint()
{
return CarbonFootPrint::getCarbonFootPrint();
}
This is legal C++, allows you to define a default implementation, and still CarbonFootprint is an abstract class.

C++ overridden virtual function not getting called [duplicate]

This question already has answers here:
What is object slicing?
(18 answers)
Closed 9 years ago.
I have the following setup:
main.cpp:
int main()
{
vector <Tour> tourList;
Tour* tour_ptr;
for (unsigned int i = 0; i < tourList.size(); i++)
{
tour_ptr = &tourList[i];
tour_ptr->display();
}
}
Tour.h:
class Tour
{
public:
virtual void display();
};
Tour.cpp:
void Tour::display()
{
cout << "Tour ID: " << getID() << "\n";
cout << "Description: " << getdescription() << "\n";
cout << "Tour Fee: $" << getfee() << "\n";
cout << "Total Bookings: " << getbookings() << "\n\n";
}
GuidedTour.h:
class GuidedTour : public Tour
{
public:
void display();
};
GuidedTour.cpp:
void GuidedTour::display()
{
Tour::display();
cout << "Max Tour Group Size: " << getMaxTourists() << "\n";
cout << "Tour Guide: " << getGuideName() << "\n";
cout << "Tour Date: " << getTourDate() << "\n\n";
}
GuidedTour inherits from the Tour class, and I've specified the display() function as virtual in the base Tour class, but for some reason, the GuidedTour display() function never gets called, only the base function gets called every time. What am I doing wrong?
Your code actually doesn't print anything as the std::vector would initially be empty. Other than that, your problem is caused by object slicing (I'm assuming that you are push_back()ing GuidedTours into the vector).
When object slicing takes place, you are storing only the Tour part of your GuidedTour object(s), and that's the reason why you are seeing the output of Tour::display().
To solve your problem, you need to store the objects polymorphically, by using (smart) pointers and dynamically-allocating your objects.
int main()
{
vector <std::unique_ptr<Tour>> tourList;
for(...) {
tourList.push_back(std::make_unique<GuidedTour>(/* constructor parameters */));
...
tourList.push_back(std::make_unique<Tour>(/* constructor parameters */));
}
for (unsigned int i = 0; i < tourList.size(); i++)
{
tourList[i]->display();
}
}
Notice that I am using std::unique_ptr/std::make_unique and not raw newed pointers. Using them would greatly ease you of the problem of manually managing and deleteing your objects, which sometimes[understatement] are the cause of bugs and undefined behavior.
Note that some people might suggest you to use boost::ptr_vector or something similar. Listen to them, especially if they give you arguments on why they are better than the alternatives.
Your problem has nothing to do with your classes, rather how you are creating the object. Each element in the tourList vector is a tour, and nothing at compile time or runtime is there to determine that they are GuidedTours. In effect, GuidedTour is never called, because I don't see a GuidedTour object in your main anywhere.
I am agree with "It'sPete". because you haven't used the GuidedTour class. It will work if you use the following method.
int main()
{
vector <GuidedTour> tourList;
Tour* tour_ptr;
for (unsigned int i = 0; i < tourList.size(); i++)
{
tour_ptr = &tourList[i];
tour_ptr->display();
}
}

How to access array from a class in c++? (closed)

I'm writing a copy constructor for my class, Vehicle, but I'm having trouble accessing an array that the class has in this constructor. I set other values using dot notation (vehi.vin) and that works fine, as expected. So I tried to access the array using the same idea vehi.accessories[0] but that seems to return a null value rather than the string that's actually there. And I know when I first initialize the class that this array does have the proper values in it because I can print them out. So my question is, how can I access an array from a class? Am I using dot notation wrong? Can I not use dot notation for arrays? Do I just need a get method?
code -
vehicle.cpp
Vehicle::Vehicle(const Vehicle& vehi)
{
//get values and set them equal to the local object's attributes
vin = vehi.vin;
for(int i = 0; i < vehi.numAccessories; i++)
{
//cout << "get here\n";
accessories[i] = vehi.accessories[i];
cout << accessories[i] << " " << vehi.accessories[i] << endl;
}
}
how accessories gets its values:
for(int i = 0; i < numAccessories; i++) //loop through file until all accessories for the car have been put into the array
{
getline(fin, accessories[i]); //put accessory in the next spot in the accessory array
cout << "Accessory " << (i+1) << ": " << accessories[i] << endl;
}
main.cpp declaration of Vehicle object. The constructor reads the values in using the file object passed to it.
Vehicle temp(fin);
vehicle.h
private:
string accessories[50]; //array of accessories stored in string form
Edit: When I try calling the copy constructor directly it works fine but when calling the printVehicle() function it seems to get there but fail somehow. The code below does what I want and shows me that the copy constructor works fine, so I guess it's the way it's invoked from printVehicle()
main.cpp:
Vehicle test(fin);
test.startAcc();
cout << endl << test.nextAcc() << endl;
Vehicle test2(test);
test2.startAcc();
cout << endl << test2.nextAcc() << endl;