I'm learning about classes and passing member variables to functions from the book "Starting out with C++: Early objects".
Right now, I'm working on a programming challenge in chapter 7 that I just can't seem to wrap my head around. My issue is I can't seem to pass the speed variable to my accelerate() function and get it to add 5 each time it's used.
I've tried modifying it several different ways, and am probably way off by now. In case you're not understanding what I'm doing, here are the instructions for the challenge:
Write a class named Car that has the following member variables:
year. An int that holds the car's model year.
make. A string object that holds the make of the car.
speed. an int that holds the car's current speed.
In additions, the class should have the following member functions.
Constructor. The constructor should accept the car's year and make as arguments and assign these values to the object's year and make member variables. The constructor should initialize the speed member variable to 0.
Accessors. Appropriate accessor functions should be created to allow values to be retrieved from an objects year, make and speed member variables.
Accelerate. The accelerate function should add 5 from the speed member variable each time it is called.
brake. The brake function should subtract 5 from the speed member variable each time it is called.
Demonstrate the class in a program that creates a Car object and then calls the accelerate function five times. After each call to the accelerate function, get the current speed of the car and display it. Then, call the brake function five times. After each call to the brake function, get the current speed of the car and display it.
Here is what I have as of now:
#include <iostream>
#include <string>
using namespace std;
class Car {
public:
int year, speed;
string make;
void accelerate(int);
void brake(int);
string getMake(string);
int getYear(int);
int getSpeed(int);
Car(int year, string make, int speed = 0) {
}
Car() {
}
};
void Car::accelerate(int s) {
speed += 5;
cout << "Your speed is " << s << endl;
}
void Car::brake(int speed) {
speed -= 5;
}
string Car::getMake(string) {
return make;
}
int Car::getYear(int) {
return year;
}
int Car::getSpeed(int) {
return speed;
}
int main() {
Car myCar;
int mySpeed = 0;
myCar.getSpeed(mySpeed);
for (int i = 1; i <= 5; i++) {
myCar.getSpeed(mySpeed);
myCar.accelerate(mySpeed);
}
}
Your code has an extra constructor that the instructions did not ask for. And neither constructor is initializing the year and speed members at all, so they start with random values (the make member is initialized to an empty string, because std::string has its own default constructor that is being called implicitly) .
Your accelerate() method is not increasing the value of the speed member, like the instructions told you to do.
Your methods all have input parameters that are unused and should be removed.
The code should look more like this instead:
#include <iostream>
#include <string>
using namespace std;
class Car
{
private:
int year, speed;
string make;
public:
Car(int yr, string mk);
void accelerate();
void brake();
string getMake();
int getYear();
int getSpeed();
};
Car::Car(int yr, string mk) :
year(yr), speed(0), make(mk)
{
}
void Car::accelerate()
{
speed += 5;
}
void Car::brake()
{
speed -= 5;
}
string Car::getMake()
{
return make;
}
int Car::getYear()
{
return year;
}
int Car::getSpeed()
{
return speed;
}
int main()
{
Car myCar(2017, "Honda");
for (int i = 1; i <= 5; i++)
{
myCar.accelerate();
cout << "Your speed is " << myCar.getSpeed() << endl;
}
for (int i = 1; i <= 5; i++)
{
myCar.brake();
cout << "Your speed is " << myCar.getSpeed() << endl;
}
return 0;
}
Related
How do I perform the same operation on different class members without duplicating code?
I have a function which creates an object of type Farm, and then performs some kind of a calculation on its members (in this case, it prints the member variable, but the code I am currently working on is too complex to copy here in its entirety):
#include <iostream>
#include <String>
class Farm
{
public:
int cows = 1;
int chickens = 2;
int mules = 3;
};
using namespace std;
void count_animals()
{
Farm* animal_farm = new Farm;
cout << animal_farm->chickens;
}
int main()
{
string animals_to_count = "count my chickens";
if (animals_to_count == "count my chickens")
count_animals();
if (animals_to_count == "count my cows")
count_animals();
if (animals_to_count == "count my mules")
count_animals();
return 0;
}
"Count my chickens" is hard-coded in main(). However, in the problem I am working on right now, animals_to_count will come from another function as an argument.
Is it possible to print cows/chickens/mules of animal_farm without using n if statements in count_animals, where n is the number of member variables?
To further clarify my problem: what I am trying to do is have 1 if statement in count_animals() which will identify which member of Farm is printed (change ->chickens to ->cows or to ->mules).
Is what I am trying possible? If not, are there other ways to work around this?
Putting your variables into a vector or other container may be the right answer.
Alternately, you can make a worker function (that you may wish to be private or protected), and getter functions with almost no code. This lets you write your complicated statistics-extraction once, with slim "getters" that make it visible in your preferred way.
class Farm
{
public:
int cows = 1;
int chickens = 2;
int mules = 3;
int get_cow_stats() {return get_complicated_thing(self.cows);}
int get_chicken_stats() {return get_complicated_thing(self.chickens);}
int get_mule_stats() {return get_complicated_thing(self.mules);}
private:
int get_complicated_thing(int animals);
};
Perhaps a pointer-to-member is what you are looking for?
#include <iostream>
using namespace std;
class Farm
{
public:
int cows = 1;
int chickens = 2;
int mules = 3;
};
int Farm::* getMemberPtr(int whichMember)
{
switch (whichMember)
{
case 0: return &Farm::chickens;
case 1: return &Farm::cows;
case 2: return &Farm::mules;
}
throw invalid_argument("");
}
void count_animals(int Farm::*member)
{
Farm animal_farm;
cout << animal_farm.*member;
}
int main()
{
int animals_to_count = ...; // 0, 1, 2, etc
int Farm::* member = getMemberPtr(animals_to_count);
count_animals(member);
return 0;
}
Online Demo
Use std::vector and constant indices:
class Farm
{
public:
std::vector<int> animal_quantity(3);
const int cow_index = 0;
const int chickens_index = 1;
const int mules_index = 2;
};
When referring to the quantity of cows:
std::cout << animal_quantity[cow_index] << "\n";
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 3 years ago.
Improve this question
\main112.cpp In function 'int main()':
63 36 \main112.cpp [Error] 'counter' was not declared in this scope
28 \Makefile.win recipe for target 'main112.o' failed
#include <string>
#include <iostream>
#include <windows.h>
#include <stdlib.h>
using namespace std;
struct Person
{
string name;
string race;
int weight;
void write();
void show();
void check();
};
void Person::show()
{
cout<<"ÔÈÎ: "<<name<<endl;
cout<<"Íîìåð ðåéñà: "<<race<<endl;
cout<<"Âåñ áàãàæà: "<<weight<<endl;
}
void Person::write()
{
cout<<"Ââåäèòå ÔÈÎ: ";
getline(cin,name);
cout<<"Ââåäèòå íîìåð ðåéñà: ";
getline(cin,race);
cout<<"Ââåäèòå âåñ áàãàæà: ";
cin>>weight;
cin.ignore();
}
void Person::check()
{
int counter = 0;
if(weight>10)
{
counter++;
}
}
int main()
{
SetConsoleCP(1251);
SetConsoleOutputCP(1251);
setlocale(0, "Russian");
Person* persons=new Person[4];
for (int i = 0; i < 4; i++)
{
persons[i].write();
}
for (int i = 0; i < 4; i++)
{
persons[i].show();
persons[i].check();
}
cout<<"Ñ áàãàæîì áîëüøå 10 êã: "<<counter<<" ÷åëîâåê"<<endl;
delete[] persons;
return 0;
}
Program that works the way its coded and should work, without this problem
Homework:
Write a program for processing passenger information. Information includes:
1) Full name of the passenger.
2) Flight number.
3) Luggage weight
The program should allow the user to:
1) Read data from the keyboard and display it.
2) Calculate the number of passengers with the weight of baggage which is more than 10 kg
The problem here is you're defining counter in the scope of the function Person::check().
Every time you run the check function a new variable called counter is created set to be the value 0. Then once it's through running that function it ceases to exist.
A quick and dirty way of fixing this would be declaring counter as a global variable.
#include <string>
#include <iostream>
#include <windows.h>
#include <stdlib.h>
using namespace std;
int counter = 0;
struct Person
{
string name;
string race;
int weight;
void write();
void show();
void check();
};
void Person::show()
{
cout<<"ÔÈÎ: "<<name<<endl;
cout<<"Íîìåð ðåéñà: "<<race<<endl;
cout<<"Âåñ áàãàæà: "<<weight<<endl;
}
void Person::write()
{
cout<<"Ââåäèòå ÔÈÎ: ";
getline(cin,name);
cout<<"Ââåäèòå íîìåð ðåéñà: ";
getline(cin,race);
cout<<"Ââåäèòå âåñ áàãàæà: ";
cin>>weight;
cin.ignore();
}
void Person::check()
{
if(weight>10)
{
counter++;
}
}
int main()
{
SetConsoleCP(1251);
SetConsoleOutputCP(1251);
setlocale(0, "Russian");
Person* persons=new Person[4];
for (int i = 0; i < 4; i++)
{
persons[i].write();
}
for (int i = 0; i < 4; i++)
{
persons[i].show();
persons[i].check();
}
cout<<"Ñ áàãàæîì áîëüøå 10 êã: "<<counter<<" ÷åëîâåê"<<endl;
delete[] persons;
return 0;
}
A better way would be defining counter as a member variable of your struct then you can get the value of each of the person objects' counter variable at anytime after declaring the object.
Familiarize yourself with the concept of scope.
Because its scope is the function Person::check, counter is only visible within the bounds of Person::check. No other parts of the program are allowed to interact with it.
Suggested solution:
Change Person::check (and its declaration) to return a boolean. Example:
bool Person::check() const
{
return weight>10;
}
The method is declared const to promise that this function will not change the object. This is done to prevent errors and allow a function that should not change the object to be used on a constant Person. This can prevent subtle errors from creeping into the code.
Now a user can check a Persons baggage weight and do with the result of check whatever they want. In the case of main, it wants to keep a count. There is no reason for anyone but main to know what it does, so counter should be scoped by main. eg:
int main()
{
...
int counter = 0;
for (int i = 0; i < 4; i++)
{
persons[i].show();
if (persons[i].check())
{
counter++;
}
}
cout<<"Ñ áàãàæîì áîëüøå 10 êã: "<<counter<<" ÷åëîâåê"<<endl;
...
}
Side note: There doesn't seem to be a need for persons to be dynamically allocated. Consider replacing
Person* persons=new Person[4];
with
Person persons[4];
and removing
delete[] persons;
If you are dynamically allocating in preparation for a variable number of Persons, prefer to use std::vector
std::vector<Person> persons;
and push_back or emplace_back Persons as they are introduced.
Here's how you fix it. Declare counter in main, make check return bool, and count the number of times it returns false. This encapsulates counter and it makes more sense for check to actually return a Boolean value. Here's what the body of for loop should do:
if (!persons[i].check())
++counter
The error message is correct, because there is no counter in main. You only declare counter here:
void Person::check()
{
int counter = 0;
if(weight>10)
{
counter++;
}
}
and its scope is limited to that method. Actually each time the function is called you get a new counter which gets initialized to 0.
If instead you make counter a member you can keep its value across multiple calls to the method:
class Person() {
public:
int counter = 0;
int check() {
if (weight > 10) ++counter;
}
// ...other stuff left out
};
I also changed the method to return the value of the counter (otherwise you would have to write a getter or some means to get its value).
I have a vector that stores multiple class objects for later access. This way my program can create new objects during runtime. This is done like so:
vector<Person> peopleVector;
peopleVector.push_back(Person(name, age));
for (int i = 0; i < peopleVector.size(); i++) {
cout << peopleVector[i].name << endl;
}
This function should print out each objects "name" every time the code runs (it's a function that runs multiple times). However, when I run this, somehow the vector does not increase in size. If you add cout << peopleVector.size(); to that code, you will find that each time it runs, it gets one (obviously assuming you also have the class code which I have below).
I'm curious why I can't create multiple objects in the class.
Class.h
#pragma once
#include <iostream>
using namespace std;
class Person {
public:
Person(string personName, int personAge);
string name;
int age;
};
Person::Person(string personName, int personAge) {
name = personName;
age = personAge;
}
Main.cpp
#include "Class.h"
#include <random>
int main() {
// Necessary for random numbers
srand(time(0));
string name = names[rand() % 82]; // Array with a lot of names
int age = 4 + (rand() % 95);
}
// Create a new person
void newPerson(string name, int age) {
vector<Person> peopleVector;
peopleVector.push_back(Person(name, age));
for (int i = 0; i < peopleVector.size(); i++) {
cout << peopleVector[i].name << endl;
}
}
Just FYI those #includes might be a little bit off because I took that code out of a large section that had like 15 includes.
You are creating an empty vector each time you call your newPerson() function, and then you add a single person to it.
You then display the contents of that vector. What else can it contain, other than the single person that you added?
Problem
Every time a function runs, all local variables inside the function are re-created in their default state. That means that every time you call newPerson, it just recreates peopleVector.
Solution
There are two solutions:
Have newPerson take a reference to a vector, and add it on to that
make peopleVector static, so that it isn't re-initialized every time
First solution:
// Create a new person; add it to peopleVector
// The function takes a reference to the vector you want to add it to
void newPerson(string name, int age, vector<Person>& peopleVector) {
peopleVector.push_back(Person(name, age));
for (int i = 0; i < peopleVector.size(); i++) {
cout << peopleVector[i].name << endl;
}
}
Second solution: mark peopleVector as static
// create a new person; add it to peopleVector
void newPerson(string name, int age) {
// Marking peopleVector as static prevents it from being re-initialized
static vector<Person> peopleVector;
peopleVector.push_back(Person(name, age));
for (int i = 0; i < peopleVector.size(); i++) {
cout << peopleVector[i].name << endl;
}
}
#include <iostream>
using namespace std;
class simpleFunction
{
protected:
int score;
public:
simpleFunction()
{
score = 5;
}
int retScore()
{
return score;
}
};
class changeFunction : public simpleFunction
{
public:
void change()
{
score = 6;
}
};
int main()
{
simpleFunction SimpleFunction;
changeFunction ChangeFunction;
cout << SimpleFunction.retScore() << endl;
ChangeFunction.change(); // Changes Score To 6
cout << SimpleFunction.retScore() << endl; // Should Return 6 But Returns 5 Instead
return 0;
}
ive set the score to 5 and when i use the change function it should change it to 6 but instead it returns the value 5.
the only way ive managed to make it work as intended to is by changing the int score variable to a global varible but all the classes can access it which makes it flawed can anyone help or try to explain this problem to me.
The Program Works but im having a problem with returning the correct values just to clear up any misunderstadnings
I am trying to make one class work with another class. It is supposed to decrement the member of the other class.
my first class is
class Bike
{
private:
int miles;
Speedometer speedom;
static int fuelCount;
public:
Bike();
Bike(int, Speedometer*); //Problem occurs here
~Bike();
int getMiles();
int getFuelCount();
void incrementMiles();
};
int Bike::fuelCount = 0;
Bike::Bike()
{
miles = 0;
fuelCount++;
}
Bike::Bike(int m, Speedometer * spm) //This is where I am having problems
{
miles = m;
speedom = &spm;
}
Bike::~Bike()
{
cout << "The Bike's destructor is running." << endl;
fuelCount--;
}
int Bike::getMiles()
{
return miles;
}
int Bike::getFuelCount()
{
return fuelCount;
}
void Bike::incrementMiles()
{
miles++;
if (miles == 999999)
miles = 0;
}
The other class which is supposed to be included in the first is:
Class Speedometer
{
private:
int fuel;
public:
Speedometer();
Speedometer(int);
~Speedometer();
int getFuel();
void incrementFuel();
void decrementFuel();
};
Speedometer::Speedometer()
{
fuel = 0;
}
Speedometer::Speedometer(int f)
{
fuel = f;
}
int Speedometer::getFuel()
{
return fuel;
}
void Speedometer::incrementFuel()
{
if (fuel <= 15)
fuel++;
}
void Speedometer::decrementFuel()
{
if (fuel > 0)
fuel--;
}
They are supposed to work together. Bike is to be able to work with speedometer object. It should decrease the speedometers current amount of fuel by one gallon for every 24 miles traveled.
This is supposed to be a aggregate relationship not composition.
Please help me just understand how to make that relationship and how its supposed to be called.
Thank you in advance.
here is my main function
btw - i have all the right #includes i just have not listed them here
int main(int argc, char *argv[])
{
Speedometer a(999970, spd);
for(int count = 0; count <=24; count++)
a.decrementMiles();
while (a.getFuel() > 0)
{
a.incrementMiles();
cout<< "Miles:" << a.getMiles() << endl;
cout<< "Fuel:" << a.getFuel() << endl;
}
return 0;
}
You have a large number of issues here.
First of all, in your main(), you construct your Speedometer object with a constructor you have not implemented. The only constructors you have defined are the default constructor and Speedometer(int). You then call Speedometer(int, ???), the ??? being spd because you do not declare spd anywhere in the code you have provided, so we have no idea what it is.
It's really impossible to say what's wrong with your code in its current state.
As written, you've made a composition; Speedometer is part of Bike since it is a field. To make it an aggregation, make Bike hold a pointer to Speedometer. Note that as a consequence, you'll probably need Bike to create or obtain an initial Speedometer (could be NULL to begin with, or pass one in the constructor), and you might want to add accessor methods to Bike in order to add/remove/change the Speedometer.
[edit] Bike might also need to know how to dispose of the Speedometer properly in order to avoid leaking it.
[edit 2] Also as #cjm571 pointed out, your main function is creating and operating directly upon a "disembodied" Speedometer. Shouldn't it be on a Bike? :)
#include <iostream>
using namespace std;
class Bike
{
private:
int miles;
static int fuelCount;
// Speedometer speedom;
public:
Bike();
Bike(int); // Speedometer *); check comment on line 82
~Bike();
int getMiles();
int getFuelCount();
void incrementMiles();
};
int Bike::fuelCount = 0;
Bike::Bike()
{
miles = 0;
fuelCount++;
}
Bike::Bike(int m)//Speedometer (*spm) I don't see the purpose of this in the current state of the program, I may not be seing the whole picture
{
miles = m;
/* speedom = spm; remember, there must be a parent and a child class, at the current state you'r trying
to call a child from parent, the child class has not been defined, so i switched them and now Bike is a chiled. */
}
Bike::~Bike()
{
cout << "The Bike's destructor is running." << endl;
fuelCount--;
}
int Bike::getMiles()
{
return miles;
}
int Bike::getFuelCount()
{
return fuelCount;
}
void Bike::incrementMiles()
{
miles++;
if (miles == 999)
miles = 0;
}
class Speedometer
{
private:
int fuel;
public:
Speedometer();
Speedometer(int f);
int getFuel();
Bike theBike; // This is what you needed in order to make incrementMiles to work.
void incrementFuel();
void decrementFuel();
};
Speedometer::Speedometer()
{
fuel = 0;
}
Speedometer::Speedometer(int f)
{
fuel = f;
}
int Speedometer::getFuel()
{
return fuel;
}
void Speedometer::incrementFuel()
{
if (fuel <= 15)
fuel++;
}
void Speedometer::decrementFuel()
{
if (fuel > 0)
fuel--;
}
int main(int argc, char *argv[])
{
Speedometer a(999); //You never declared this, did you mean spm???
for(int count = 0; count <=24; count++)
a.theBike.incrementMiles();
while (a.getFuel() > 0)
{
a.theBike.incrementMiles();
cout<< "Miles:" << a.theBike.getMiles() << endl;
cout<< "Fuel:" << a.getFuel() << endl;
}
cin.get();
return 0;
} //There is no break declared (that i can see at least) so the program runs an infinite loop
// Don't want to add too many things to it, I don't know what your plan is.
// Hoping to have made it clearer.