C++ Can You Change A Protected Variable in a Base Class - c++

#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

Related

Perform same operation on different class members without duplicate code

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";

Error - int 'counter' was not declared in this scope [closed]

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).

Accessor Method to view private variable based on argument in a class in c++?

My problem is that I have many variables in my class and I want them to be accessed via an accessor method. Of course I could have several accessor functions to output my private variables but how can I make it so I can access any of them via an argument. My class:
class Character {
public:
void setAttr(string Sname,int Shealth,int SattackLevel,int SdefenseLevel) {
name = Sname;
health = Shealth;
attackLevel = SattackLevel;
defenseLevel = SdefenseLevel;
}
int outputInt(string whatToOutput) {
return whatToOutput //I want this to either be health, attackLevel or defenseLevel
}
private:
string name;
int health;
int attackLevel;
int defenseLevel;
};
Basically what I want to know is how do I return a private variable in regards to the outputInt function. Most OOP tutorials have one function to return each variable which seems like a very unhealthy thing to do in a large program.
C++ doesn't support what you try to accomplish: reflection or detailed runtime information about objects. There is something called "Run-Time Type Information" in C++, but it can't provide information about your variable name: the reason is because, in the compiled and linked binary this information (names of your variables) will not be necessarily present anymore.
However, you can accomplish something close to that, using i.e. std::unordered_map instead of plain integer variables. So it's possible to access values by their names, as strings.
Please consider the following code:
#include <string>
#include <iostream>
#include <unordered_map>
using namespace std;
class Character {
public:
void setAttr(const string& Sname, int Shealth, int SattackLevel, int SdefenseLevel) {
name = Sname;
values.insert(std::make_pair("health", Shealth));
values.insert(std::make_pair("attackLevel", SattackLevel));
values.insert(std::make_pair("defenseLevel", SdefenseLevel));
}
int outputInt(const string& whatToOutput) {
return values.at(whatToOutput);
}
private:
string name;
std::unordered_map<std::string, int> values;
};
int main(int argc, char* argv[]) {
Character yourCharacter;
yourCharacter.setAttr("yourName", 10, 100, 1000);
std::cout << "Health: " << yourCharacter.outputInt("health") <<std::endl;
std::cout << "Attack level: " << yourCharacter.outputInt("attackLevel") << std::endl;
std::cout << "Defense level: " << yourCharacter.outputInt("defenseLevel") << std::endl;
return 0;
}
It will output as expected:
Health: 10
Attack level: 100
Defense level: 1000
Another option without dependency on unordered_map would be, to use predefined static strings for your variable names and an array or vector for your values. So we could replace the class Character above with something like:
static std::string variableNames[3] = {
"health",
"attackLevel",
"defenseLevel"
};
class Character {
public:
void setAttr(const string& Sname, int Shealth, int SattackLevel, int SdefenseLevel) {
name = Sname;
variableValues[0] = Shealth;
variableValues[1] = SattackLevel;
variableValues[2] = SdefenseLevel;
}
int outputInt(const string& whatToOutput) {
int retVal = 0;
for (size_t i = 0; i < sizeof(variableNames)/sizeof(std::string); ++i) {
if (!whatToOutput.compare(variableNames[i])) {
retVal = variableValues[i];
}
}
return retVal;
}
private:
string name;
int variableValues[3];
};
And getting still same output. However, here you have to manage a list with all your variable names inside the string array manually - I don't like this solution and would prefer one of the others above personally.
Most common ways in C++ to handle such a design is to have seperate getHealth(), getAttackLevel(), getDefenseLevel() functions instead. However, this will miss one use-case, which is: if you want to let the user input a string, like i.e. "health" and display the corresponding variable then, you would need to write code by yourself to call the corresponding getXXX() function. If this is not a issue in your case, consider the following code which is much cleaner:
#include <string>
#include <iostream>
using namespace std;
class Character {
public:
void setAttr(const string& Sname, int Shealth, int SattackLevel, int SdefenseLevel) {
name = Sname;
health = Shealth;
attackLevel = SattackLevel;
defenseLevel = SdefenseLevel;
}
int getHealth() const { return health; }
int getAttackLevel() const { return attackLevel; }
int getDefenseLevel() const { return defenseLevel; }
private:
string name;
int health, attackLevel, defenseLevel;
};
int main(int argc, char* argv[]) {
Character yourCharacter;
yourCharacter.setAttr("yourName", 10, 100, 1000);
std::cout << "Health: " << yourCharacter.getHealth() <<std::endl;
std::cout << "Attack level: " << yourCharacter.getAttackLevel() << std::endl;
std::cout << "Defense level: " << yourCharacter.getDefenseLevel() << std::endl;
return 0;
}
One other unrelated advice: Instead of using string as parameter types for your functions, use const string& (const reference to string; see my example code above). This allows easier calling of your functions (they can be called directly with an string literal without the need to create additional variables in the calling code) and they will not make a additional unnecessary copy. The only copy then will take place at: name = Sname; (in your code two copies took place).
I don't know if it can be a good idea for you, but you can use a public typedef struct that you pass by reference and set your value.
class Character {
public:
//...
typedef struct allvalues{
string vname;
int vhealth;
int vattackLevel;
int vdefenseLevel;
}allvalues;
void getValues(allvalues& val){
val.vname = name;
val.vhealth = health;
val.vattackLevel = attackLevel;
val.vdefenseLevel = detenseLevel;
}
//...
};
//...
//somewhere in the code
Character myCarac;
//...
//Here how to use it
Character::allvalues values;
myCarac.getValues(values);

C++ "No matching constructor for initializing Employee"

I am new to C++ and practicing using vector as an object. However, I got an error "No matching constructor for initializing Employee" when I tried running the following program.
Please tell me how I could modify my program!
Also, when I write
staff[0] = Employee{"Harry Potter" 55000};
does this mean that I am storing string and double data in one of 10 open boxes in vector object of type Employee?
I apologize for such a basic question.
Thank you so much in advance!!
#include<iostream>
#include<string>
#include<vector>
using namespace std;
class Employee
{
public:
Employee(string, double);
double get_salaries();
string get_name();
void set_salaries(double);
private:
string name;
double salaries;
};
Employee::Employee(string n, double s)
{
name = n;
salaries = s;
}
double Employee::get_salaries()
{
return salaries;
}
string Employee::get_name()
{
return name;
}
void Employee::set_salaries(double s)
{
salaries = s;
}
int main()
{
// using vector as an object
int i;
vector<Employee> staff(10);
staff[0] = Employee{"Harry Potter", 55000};
if (staff[i].get_salaries() < 100000)
cout << staff[i].get_salaries();
return 0;
}
Your Employee class does not have a default, parameterless, constructor.
When you create the staff vector, it will create 10 Employee objects, thus invoking the default constructor.
To support this,
vector<Employee> staff(10);
you have to provide default constructor in your class.
Your main method
int main()
{
// using vector as an object
int i; // [i] not initialized anywhere.
vector<Employee> staff(10); // Incorrect way of declaring a vector
staff[0] = Employee{"Harry Potter", 55000}; // Incorrect way of creating a instance of class
if (staff[i].get_salaries() < 100000)
cout << staff[i].get_salaries();
return 0;
}
Change your main method like this
int main()
{
vector<Employee> staff;
staff.push_back(Employee("Harry Potter", 55000));
if (staff[0].get_salaries() < 100000)
cout << staff[0].get_salaries();
return 0;
}

Aggregation using C++

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.