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.
Related
I have a class that has to store the weight of the animal and it's type.
Depending on what the user wants, there can be as many instances of that class created at runtime.
My problem is with not being able to properly declare a dynamic array that can resize itself once the entire array has been filled with objects.
class FarmAnimal
{
private:
short int type;
int weight;
double WaterConsumed;
public:
static int NumberOfSheep;
static int NumberOfHorse;
static int NumberOfCow ;
static double TotalWaterUsed;
FarmAnimal(int type, int weight)
{
this->type = type;
this->weight = weight;
}
int CalculateWaterConsumption(void);
void ReturnFarmInfo(int& NumberOfSheep, int& NumberOfHorse, int& NumberOfCow, int& TotalWaterUsed)
};
int main()
{
...
short int k;
...
do
{
...
FarmAnimal animal[k](TypeOfAnimal, weight);
k++;
cout << "Would you like to add another animal to your farm?\n Press\"0\" to exit and anything else to continue" << endl;
cin >> ExitButton;
} while (ExitButton != 0)
and the end of the program
animal[0].ReturnFarmInfo(NumberOfSheep, NumberOfHorse, NumberOfCow, TotalWaterUsed)
cout << " Your farm is made up of :" << NumberOfSheep << " sheeps " << NumberOfHorse" horses " << NumberOfCow << " cows " << endl;
cout << "The total water consumption on your farm per day is: " << TotalWaterUsed << endl;
}
Array cannot change size in C++. You need to use a dynamic container such as std::vector. A documentation of the vector class can be found here.
std::vector<FarmAnimal> animals;
bool done = false;
while (!done)
{
animals.push_back(FarmAnimal(TypeOfAnimal, weight));
cout << "Would you like to add another animal to your farm?\n Press\"0\" to exit and anything else to continue" << endl;
cin >> ExitButton;
done = (ExitButton != 0);
}
Use the std::vector from the standard library and the method push_back() to add new elements
http://www.cplusplus.com/reference/vector/vector/
As mentioned in the comments by Some programmer dude and Ron, variable-length arrays are not supported in C++ by default. The std::vector class is a useful tool should you require them.
Some basic info about vectors:
http://www.cplusplus.com/reference/vector/vector/
I'm trying to find a way to get an iterator to work on a list of custom objects and a list of objects derived from that custom object. My, perhaps misguided, goal is to allow me to leave the "production" code and objects intact yet accessible from the "experimental/extended" things that I'm trying out.
Here's a pretty minimal example of what I'm trying to do.
#include <iostream>
#include <list>
using std::cout;
using std::endl;
using std::cin;
using std::list;
struct comp{
double x,y;
void print(){
cout << "x: " << x << endl;
cout << "y: " << y << endl;
}
comp(){
x = 0;
y = 0;
}
comp(double X, double Y){
x = X;
y = Y;
}
// Standard/Tested Member Functions
};
struct base{
list<comp> components;
double known, tested, variables;
void print_comps(){
for (list<comp>::iterator it = components.begin(); it != components.end(); ++it){
// Ideally, this function should work for comp1 and comp1x
// as inherited in the basex class
it->print();
}
}
// Standard/Tested Member Functions
};
struct compx : comp{
double w,z;
double some, alter, nates;
void print(){
cout << "x: " << x << endl;
cout << "y: " << y << endl;
cout << "w: " << w << endl;
cout << "z: " << z << endl;
}
compx(){
x = 0;
y = 0;
z = 0;
w = 0;
}
compx(double X, double Y, double Z, double W){
x = X;
y = Y;
z = Z;
w = W;
}
// Experimental/Un-tested Member Functions
};
struct basex : base{
list<compx> components;
double exper, imen, tal;
// void print_comps(){} // This should be inherited from base
// Experimental/Un-tested Member Functions
};
int main(){
base compilation1;
compilation1.components.push_back(comp(1,2));
compilation1.components.push_back(comp(3,4));
cout << "printing normal struct" << endl;
compilation1.print_comps();
cout << endl;
basex compilation2;
compilation2.components.push_back(compx(9, 5, 5, 6));
compilation2.components.push_back(compx(7, 2, 1, 8));
cout << "printing extended struct" << endl;
compilation2.print_comps(); // Prints nothing
cout << endl;
cout << "Printing via specific iterator" << endl;
for (list<compx>::iterator it = compilation2.components.begin(); it != compilation2.components.end(); ++it){
it->print(); // Works as expected.
}
cout << endl << endl << "Press ENTER to exit." << endl; cin.get();
return 0;
}
Ideally, I would be able to iterate over both the original class and the extended class in the same functions so I don't clutter the extended class with all the original code. This would allow me to simply move code from the extended class to the original class as those variables or functions are proven or matured.
Background:
I'm not married to lists -- any other iterable class would be fine.
I'm not a developer -- I'm a ChemE trying to make daily tasks a bit easier without breaking what I've already built.
Branches in a git repository are not a great solution because other non-developer, potentially code-challenged, folks may try to extend this. Getting them to use even one branch would be a miracle.
I'm using g++ 7.4.0 on Linux (Lubuntu) and 6.3.0 on Windows 7.
TL;DR:
Is there a way to get an iterator of list<parent_object> to also iterate over list<child_object>?
This could be solved by having base as a template http://cpp.sh/7r2x6a
template<typename T>
struct base
{
list<T> components;
double known, tested, variables;
void print_comps(){
for (auto it = components.begin(); it != components.end(); ++it){
// Ideally, this function should work for comp1 and comp1x
// as inherited in the basex class
it->print();
}
}
// Standard/Tested Member Functions
};
If you're okay with not being able to mix comp and compx objects together in the same list, then you can use a templated function to avoid duplicate code.
For example, you can do the following in your struct base:
struct base{
list<comp> components;
double known, tested, variables;
void print_comps() {print_comps_aux<comp>(components);}
protected:
template <typename CompType> void print_comps_aux(list<CompType> & compsArg)
{
for (typename list<CompType>::iterator it = compsArg.begin(); it != compsArg.end(); ++it){
it->print();
}
}
// Standard/Tested Member Functions
};
... and then in your struct basex you can just have this:
[...]
void print_comps() {print_comps_aux<compx>(components);}
I have a mother class and a derived daughter class. I am trying to access the protected variable 'familystuff' in the derived class. Both ways that I am trying to access it aren't working. When I compile and run it, I get the following output:
5 3 1
1
Familie 32768
FOO 32767
class Mother
{
private:
int motherstuff;
protected:
int familystuff;
public:
int everyonesstuff;
void SetStuff(int a, int b, int c){
motherstuff = a;
familystuff = b;
everyonesstuff = c;
}
void Show(){
cout << motherstuff << " " << familystuff << " " <<everyonesstuff << endl;
}
};
class Daughter : public Mother
{
public:
Daughter()
{
a = familystuff + 1;
}
void Show(){
cout << "Familie " << a << endl;
}
int foo() { return familystuff;}
private:
int a;
};
int main(){
Mother myMum;
myMum.SetStuff(5,3,1);
myMum.Show();
cout << myMum.everyonesstuff << endl;
Daughter myDaughter;
myDaughter.Show();
cout << "FOO " << myDaughter.foo() << endl;
}
You don't have a clear concept in object oriented programming. When you create two objects, then they are completely different from each other. They do not interact with each other until they are forced.So,
myMum and myDaughter are seperate objects and they do not share the values of their variables.
The last two outputs are basically garbage values. You have not initialized myDaughter's familystuff
So, if you want to access protected members from derived class, you need to write the following :
int main()
{
Daughter myDaughter(5,3,1);
myDaughter.Show();
cout << "FOO " << myDaughter.foo() << endl;
}
Change the Daughter's constructor to the following :
Daughter(int x,int y,int z)
{
SetStuff(x,y,z);
a = familystuff + 1;
}
You will get the desired output!!
There are several things wrong here:
myDaughter and myMum are different objects. You imply some kind of relationship between them, but there is none.
Your code has undefined behaviour, because your Daughter constructor uses the uninitialised member variable familystuff in an addition operation.
You should initialise your data members like this:
Mother::Mother() : motherstuff(0), familystuff(0), everyonesstuff(0) {}
Daughter::Daugher() : a(familystuff + 1) {}
I am just started learning OOP concepts and to help myself learning, I have created a Characters class. From this class I have made instance called main and an instance called monster. Here is the code for the class:
#include <iostream>
#include <string>
using namespace std;
class Character {
public:
string name;
float health;
int attackLevel;
int defenseLevel;
void setAttr(string sName,float sHealth, int sAttackLevel, int sDefenseLevel) {
name = sName;
health = sHealth;
attackLevel = sAttackLevel;
defenseLevel = sDefenseLevel;
}
void attack(int whatInstanceToAttack) {
whatInstanceToAttack.hitpoints -= 20; //obviously not valid but how do i do this?
return whatInstanceToAttack;
}
int defend(string defend) {
int damageRelieved = defenseLevel * 2;
return damageRelieved;
}
};
int main() {
Character main;
Character monster;
main.setAttr("Rafael",200,100,30);
monster.setAttr("Monster1",30,40,30);
cout << "Default Values for Raf are;" << endl;
cout << main.name << endl;
cout << main.health<< endl;
cout << main.attackLevel << endl;
cout << main.defenseLevel << endl;
cout << "Default values for monster are" << endl;
cout <<monster.name << endl;
cout <<monster.health << endl;
cout << monster.attackLevel<< endl;
cout << monster.defenseLevel << endl;
return 0;
}
Basically what I want to do is somehow access the monster instance via the main instance. I want to do this by running the attack method. So if I run
main.attack(monster);
then I want the monster to lose 20 hitpoints.
How do I go about doing this?
All you need is to pass reference of Character in attack method.
I think you must be aware of pass by value and pass by reference concept. If not you can read it here
void attack(Character &whatInstanceToAttack) {
whatInstanceToAttack.hitpoints -= 20; //obviously not valid but how do i do this?
}
Yes you can access the variables of an instance from another instance of the same class. You need to use a reference to the object to ensure the changes are reflected in the other instance. So here is what your attack function should look like.
void attack(Character &c)
{
c.hitpoints - = 20;
}
Now when you call main.attack(monster) from the main() function, the hitpoints of monster will get decremented by 20.
As a side note, it is considered a good practice to make the data members of a class private, to avoid illegal access/modification of the data. Always use the member functions as an interface to your class instances.
overload the method attack and you can pass by value or reference as per your requirement.
void attack(Character chr)
or
void attack(Character &chr)
I've been at this for a few hours now. I am making a small game in C++ and I am trying to figure out how I can edit variables from inside of a function. I can place the variables in the main() and edit them them there no problem, but I can't figure out what I need to do to edit from a function. Below is the function.
void HeroSelect(string& hero)
{
int gold = 20, health = 5, attack = 5, stats[2] = { health, attack };
string weapon;
cout << "Please choose your hero.\n";
cin >> hero;
if (hero == "Warrior" || hero == "warrior")
{
weapon = "Broad Sword";
cout << "You are a Warrior wielding a " << weapon << endl;
cout << "Good choice.\n"
<< "You start out with " << gold << " gold." << endl
<< "You have " << stats[0]<< " health and " << stats[1] << " attack.\n";
}
Above is the function definition and I want to be able to edit the health when the player gets attacked or say gets a stronger weapon. Below is the main() of the script.
void main()
{
double enter, room1, room2, room3, room4, BossRoom;
int, gold = 20; //This is used as part of check inventory and will be subtracted when necessary
string hero, weapon;
//Set decimal two places
cout.setf(ios::fixed);
cout.setf(ios::showpoint);
cout.precision(2);
Intro(enter);
cout << "The first step in this adventure is to choose your hero. You can choose a warrior, a wizard, or an archer.\n";
HeroSelect(hero);
So let's say he gets a new weapon and it gives +1 attack how do I reflect that in the function? Would I create a separate function for this?
As the player goes through the game, they can type in "stats" whenever, and when they do I want it to display their current health and attack and then essentially just loop back to the beginning of the room or fight they are in.
I know I can make the changes to the variables if I made all of my loops and all of my if-else statements in main(), but I wanted to try this and keep my main script clean. I did stats as an array, because I think it is good to print the array as a list. Any help would be great. Thanks!
You may need to do a refresher on C++ and OOP. Your concept is not bad, but you can possibly make it better. (Granted if you really want to do something in a particular fashion, and you are able to do it in such fashion, then by all means just do it :P).
As mentioned in your comments, a re-engineering of the game design may be in order. You will want to establish a Hero class, with multiple variables or sub-classes as the attributes (for example: strength, health points, weapons class, armor class, etc. (We could go into a lower-level description, but i don't think it's necessary yet). If you plan to have multiple weapons, a weapons class might be a good idea as well, for example you could define the weapon stats: attack damage, attack rate, weapon durability etc...
In these classes you can create "Helper Functions" which you can then use to change the stats of the associated objects. Helper function could be public functions which would allow you to increment/decrement hero health or perhaps a helper function that will increase attack damage?
It seems like you're doing a good job learning, so hopefully you can visualize the idea here. Either way, keep on grinding and feel free to ask for a more in depth answer whenever necessary! I'd love to see your game when your ready for some testing!
There are several ways to handle this.
The first being to create a class which is covered in the comments and the answer by ejsd1989.
The second option is to make these variables global variables by creating them in the main and just pass them through each function by reference. This keeps your main clean like you desired.
For example:
void HeroSelect(string& hero, int &gold, int &health)
The third option is very similar to the second, and it is to store these variables in an array and just modify the array with each function.
Essentially, it boils down to creating a class or passing the variables to the functions you wish to use.
Main is not a script and there are some conceptual problems with design in question. Word by word answer would be: pass function parameters by reference. But it would not be a good solution for the task.
Please consider this example:
uint menu;
Hero * hero;
Room entrance, next[5];
entrance.Enter();
std::cout << "1st step in this adventure is to choose your hero." <<std::endl;
std::cout << "You can choose " <<std::endl;
std::cout << "(1) a warrior " << std::endl;
std::cout << "(2) , a wizard" << std::endl;
std::cout << "(3) , or an archer." << std::endl;
std::cout << "Please choose your hero." << std::endl;
std::cin >> menu;
switch( menu )
{
case 3 : { hero = new Archer; break; }
case 2 : { hero = new Wizard; break; }
default : { hero = new Warrior; break; }
}
hero->Weapon();
hero->Gold();
hero->Health();
hero->Attack();
std::cout << "Which room to enter? 1..5" << std::endl;
std::cin >> menu;
next[menu - 1].Enter();
if( 5 == menu )
{
std::cout << "You are attacked by a troll!" << std::endl;
hero->SetHealth( hero->GetHealth() >> 1 );
}
hero->Health();
You can handle hero types, room instances this way. Find properties of them that could be generalized and make differences via members or inheritance. Design it more carefully and you could minimize e. g. tons of couts and duplicated code branches.
class Room
{
static uint cntr;
std::string name;
public:
Room() : name ( "Room#" ) { if( cntr < 5 ) { name[ name.size() - 1 ] = cntr + '0'; } else { name = "BossRoom"; } ++cntr; }
void Enter() { std::cout << "You have entered " << name << "!" << std::endl; }
};
uint Room::cntr;
struct Limint
{
uint max;
uint curr;
Limint( uint init ) : max ( init ), curr( init ) {}
};
class Hero
{
protected:
std::string type;
uint gold;
Limint hp;
Limint attack;
std::string weapon;
public:
Hero() : type( "Hero" ), gold( 20 ), hp( 50 ), attack(5), weapon( "Kitchen knife" ) {}
uint GetHealth() { return hp.curr; }
void SetHealth( uint health ) { health = std::min( health, hp.max ); hp.curr = health; }
void Weapon() { std::cout << "You are a " << type << " wielding a " << weapon << ". Good choice!" << std::endl; }
void Gold() { std::cout << "You start out with " << gold << " gold." << std::endl; }
void Health() { std::cout << "You have " << hp.curr << " / " << hp.max << " health." << std::endl; }
void Attack() { std::cout << "You have " << attack.curr << " / " << attack.max << " attack." << std::endl; }
};
class Warrior : public Hero
{
public:
Warrior() { type = "Warrior"; weapon = "Broad sword"; }
};
class Wizard : public Hero
{
public:
Wizard() { type = "Wizard"; weapon = "Magic stick"; }
};
class Archer : public Hero
{
public:
Archer() { type = "Archer"; weapon = "Crossbow"; }
};
Have fun!