Operations with objects - Practicing for the exam - OOP [closed] - c++

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 7 years ago.
Improve this question
Current state of my solution
#include <iostream>
class money {
int kn, lp;
public:
void add(int kn, int lp){
this->kn+=kn;
this->lp+=lp;
if(this->lp>=100){
this->kn++;
this->lp-=100;}
}
void print() {
std::cout<<this->kn<<" kuna";
if(this->lp!=0) std::cout<<", "<<this->lp<<" lipa";
}
};
int main () {
//money a(7, 50) , b(3, 70) , c(2, 80);
money a;
//simplified
a.add(3, 70);
a.add(2, 80);
a.print();
}
Task requires me to expand the class, so that the below program correctly adds the money and prints it. http://prntscr.com/711bs5
I simplified the task, because I'm still getting to the final solution. But I don't know why does it print garbage? And after I solve that.
Can someone help me in short tips, what's needed to correctly solve the task. Obviously when I'm instancing those objects, I'm supposed to add to object a, the values from objects b and c. But I don't know how to do that, I missed a few lessons.
EDIT: Why do people downvote? Am I missing something? Too trivial question? Bad title?

For the first part: initialize.
For the second part you have to create a method taking another instance of class money as a parameter and add the values of kn and ln to the ones of the existing.
#karma:
It's not a formula, but there is no check how money values have to be entered.
The smartest thing in my opinion would be to check the correct behavior while instancing an object (in the constructor), so that objects can only be of form:
0<=lp<=99;
edit2:
How do you create this method?
For ones, since your add method already exists you can OVERLOAD it. This means you create a method with the same name and return type, but having different parameters.
So you can create another method add and pass a money instance to it, as already mentioned. If you don't understand that, you should really have a look at how methods work and how to create them and that basically anything can be passed to them (not just primitive types).

You need to initialize the variables before you use them.
When you use variables without initializing them, you get garbage values. For instance, here:
this->kn+=kn;
this->lp+=lp;
both of them are uninitialized.
For data members of a class, you can initialize using a constructor as follows:
money()
{
kn=0; lp=0;
}
So, your code now becomes:
#include <iostream>
class money {
int kn, lp;
public:
money()
{
kn=0; lp=0;
}
void add(int kn, int lp){
this->kn+=kn;
this->lp+=lp;
if(this->lp>=100){
this->kn += this->lp/100; this->lp %= 100;}
}
void print() {
std::cout<<this->kn<<" kuna";
if(this->lp!=0) std::cout<<", "<<this->lp<<" lipa";
}
};
int main () {
//money a(7, 50) , b(3, 70) , c(2, 80);
money a;
//simplified
a.add(3, 70);
a.add(2, 80);
a.print();
return 0;
}

Related

How do I wait until a variable reaches a certain number to do something? [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 6 years ago.
Improve this question
I am creating a game in C++. In this game, I have created a class called Player. The Player class has an attribute called magic. This attribute is an integer and constantly goes up throughout the game, when a user does something or accomplishes a task, they can gain magic. Once it reaches a certain point, the user gets a new spell, the spells are held in an array in the player class.
I want to be able to check this attribute throughout the game to see if it has reached a certain level.
I was thinking of just checking every time the magic attribute goes up, but this could add a lot of conditionals every time it does so. Such as:
user.magic++
if(user.magic == 2) {
//Give a new spell
}
else if(user.magic == 3) {
//Give a new spell
}
And do this every time the magic attribute is updated. This seems like it would take a lot of time and effort to constantly type this. Should I put the code above in a function and just run it every time the magic updates?
Is there a better way to do this?
Make the .magic member variable private so that the only way to increase magic is to call a method such as user.IncrementMagic() rather than being allowed to say user.magic++ directly. Then, the implementation of the method might look something like:
Player::IncrementMagic()
{
magic++;
CheckUpdatedMagicLevel();
}
Player::CheckUpdatedMagicLevel()
{
if(magic == 2)
{
// etc
}
// etc
}
If needed, you could also write further methods that manipulate magic in different ways—e.g. DecrementMagic or SetNewMagicLevel(x). These methods would also call CheckUpdatedMagicLevel() internally.
First step: you decouple the user.magic from the spells available. Reason: maybe in the future you want to assign spells for NPC-es as well, not only users.
struct spell {
int type;
int cost;
int damage;
}
static const spell walk_on_water={SURVIVAL, 10, 0};
static const spell resurect={DARK_MAGIC, 100, 0};
static const spell fireball_minor={OFFENSIVE, 30, 4};
static const spell fireball_big={OFFENSIVE, 300, 25};
void getSpellsForMagicLevel(int userMagic, std::vector<const spell&>& resultHere) {
resultHere.clear();
switch(useMagic) {
case 1:
resultHere.push_back(walk_on_water);
break;
case 2:
resultHere.push_back(walk_on_water);
resultHere.push_back(fireball_minor);
break;
//...
case 10:
resultHere.push_back(walk_on_water);
resultHere.push_back(resurect);
resultHere.push_back(fireball_minor);
resultHere.push_back(fireball_big);
break;
}
}
and then you call this single function any time you want to know what available spells are there for a player.magic
Then you note that user's spell inventory only changes when the magic modifies (up - due to increased experience - or down e.g. due to a damaging potion) - so why rely on calling this function again and again? So:
class Player {
protected:
int magic;
std::vector<const spell&> spell_inventory;
// ...
void set_magic_level(int newMagicLevel) {
if(this->magic != newMagicLevel) { // do nothing if no change
this->magic = newMagicLevel;
getSpellsForMagicLevel(this->magic, this->spell_inventory);
}
}
// ...
public:
// ...
int get_magic_level() const {
return this->magic;
}
};
class User : public Player {
//...
public:
void newExperience(const Event& somethingThatHappened)
{
switch(somethingThatHappened.type) {
case EXPERIENCE_THRESHOLD_REACHED:
this->set_magic_level(this->get_magic_level()+1);
break;
case DUMBING_POTION:
this->set_magic_level(
this->get_magic_level()-somethingThatHappened.get_damage()
);
break;
// etc...
}
}
};
class NonPlayerCharacter : public Player {
//...
public:
// NPC-es don't evolve, they are just spawned
// So no newExperience method for them.
};
How about use a map? so you can use the number of mana required to unlock certain spells (aka int) as keys and store strings or other implements for unlocked spells and grant the player such spells. I mean, technically it is better than having tons of hardcoded if loops, in this implementation you can just change the map and use the same function.
edited for another way to design this, you give the player all the spells from the beginning but limit it by "can only cast certain spell when match MAGIC requirements", which you can still use map as a handy tool
Increasing the value "constantly" (with a timer? every time a certain command is issued?) is possible, but then your step of 1 to add a new spell is way too small. It would mean that on every action you get a new spell!
Instead, use something like this: set an experience value to 0. Then, in your main loop (that same timer, or whatever you are using), increase this value. If it reaches some reasonable value, say, 100, add a new spell and reset the experience value back to 0.

How to allow a program to create new objects [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 6 years ago.
Improve this question
Thanks so much for taking the time to look at my question!
Right now I am working with classes and objects. I am trying to write a program that stores information about visitors to a hotel. A user will input the name of the visitor and some information about them. The program will then store that information in an object and be able to calculate how much to charge for the users stay.
The problem that I am running into is that I don't know how to let the program create new objects for the visitors. For example, if Sally came in I would like to create a new object for her within the program that could store her information.
I have looked at dynamic object creation and done a fair amount of Googling on the subject but can't seem to find any answers. Here is a simplified version of what I would like to do:
#include "stdafx.h"
#include <iostream>
#include <string>
using namespace std;
class visitor {
public:
string name;
int age;
};
int main()
{
//a new person comes to the hotel, the person at the desk gives the program his/her name
//and age and it is put into a class so it can be used later.
}
If there is a better way to accomplish this I would love suggestions, I am but a fledgling programmer and it is very possible that I am approaching this incorrectly.
Thanks in advance!
You have done fine, so far.
class visitor {
public:
string name;
int age;
};
int main()
{
//a new person comes to the hotel, the person at the desk
//gives the program his/her name
//and age and it is put into a class so it can be used later.
}
Now remember how easy it is to define a integer value i, and initialize it with 0:
int i = 0;
Your class is just like "int". So name a variable declared just like int.
visitor guest1;
You should write a default ctor to initialize the contents. Note that your code has a default ctor provided by the compiler. But what it does (nothing) is not terribly useful.
And then write a non-default ctor to fill in the contents.
and so on, and so on.
How about a show method to display values.
guest1.show();
Good luck.
You need to create a constructor. This is a function that constructs visitors. We write that as follows:
class Visitor {
public:
string name;
int age;
Visitor(string name, int age) {
this->name = name;
this->age = age;
}
};
We can then create a new Visitor object (note that its usual convention to make a class name's first letter uppercase) with the following:
Visitor sally = Visitor("Sally", 22);
To allow the user to input what we want the name and age to be, you should look at another SO answer like Getting user input in C++.
EDIT: You don't need to create a constructor as the compiler will make one by default in this case, but it will be useful for you to learn by creating your own constructors for the time being, so you know what's happening.

How do i change an object through the use of pointers?

#include "Visit.h"
class Patient
{
private:
std::string name;
std::string IC;
List<Visit> *visitList;
List<MC> mcList;
public:
Patient();
Patient(std::string, std::string);
void addVisit(Visit);
List<Visit> *getVisitList();
};
//End of Patient.h
#include "Patient.h"
Patient::Patient()
{
visitList = new List<Visit>();
}
Patient::Patient(std::string ic, std::string n) : name(n), IC(ic)
{
visitList = new List<Visit>();
}
void Patient::addVisit(Visit v)
{
visitList->add(v);
}
List<Visit> * Patient::getVisitList()
{
return visitList;
}
//End of Patient.cpp
class Visit
{
private:
__int64 time;
double cost;
bool xRayStatus = false;
public:
Visit();
Visit(__int64, double);
void addXRay();
bool getXRayStatus();
};
//End of Visit.h
#include "Visit.h"
Visit::Visit() {
}
Visit::Visit(__int64 t, double c) : time(t), cost(c) {
}
void Visit::addXRay()
{
xRayStatus = true;
}
bool Visit::getXRayStatus()
{
return xRayStatus;
};
//End of Visit.cpp
int main()
{
int pos;
Visit v(/*current time, cost*/);
Patient p()
unordered_map<string, Patient> patientMap;
string IC;
getline(cin,IC);
Patient p(IC, "John");
patientMap.insert({IC, p});
Patient *pc;
Visit *vc;
pos = patientMap[IC].getVisitList()->getLength();
pc = &patientMap[IC];
pc->addVisit(v); //Debugger shows patientMap[IC].getVisitList()->getLength() becomes 2
pc->getVisitList()->get(pos).addXRay(); //patientMap[IC].getVistList()->get(0).getXRayStatus() still false
vc = &patientMap[IC].getVisitList()->get(pos);
vc->addXRay(); //patientMap[IC].getVistList()->get(0).getXRayStatus() still false
}
How do i make that getXRayStatus true? It seems odd to me that i can add items into the list but not carry out other functions like vc->addXRay.
vc itself shows true but the change isn't reflected on my map.
pc somehow is able to add Visits and show the change on the map.
In the List<Visit> you are keeping instances of Visits. When you are setting the xRayStatus you are changing the status of the local Visit copy you get from the list, not to the actual object in the list.
In an extended comment conversation, the asker has asked for general redesign help to avoid the problems caused by working with a Visit copy from get(). My redesign suggestions are:
stop using List. Whether you wrote it yourself or got it somewhere else, it's surely more than you need. Use std::vector<> as the collection class of first choice, and change to something else only when you need it.
don't keep pointers to your collections in Patient unless they are likely to be enormous memory hogs. Have vectors as member variables. This will save you having to write a lot of cleanup code.
Stop keeping solid Visit objects in the collections. Use make-shared() or make_unique to get yourself smart pointers to visit objects that are on the heap. Keep these pointers in the vectors and you can deference them to change the real values in the real visits out on the heap
consider adding a date and time or visit number to Visit since at the moment it's not clear to me how you find a specific visit when there is more than one
set properties in things before you put them in collections. Your main knows all about the inside of a Visit (not that I approve of that) but has Patient create an empty one and then jumps through hoops trying to get hold of it and change some of its properties. Why not have Patient set those properties? Or have main() create a Visit, fill in all the properties, and then hand it to Patient saying "here, add this to your collection"? What you're doing now is so much harder than it needs to be.
Finally, find a tutorial, book, or online course that works for you and gets you clear on the difference between objects and pointers, good reasons for using pointers, the need for destructors (you have none at the moment) and for good measure explains the collection classes in std:: and elsewhere. Tutorials and architectural advice are not a good fit for the Q&A mechanism of StackOverflow.

Overload constructors for a class structure with more than one instance of that class structure

Hello to all that read
I am self learning C++ from a text book.
...and I have been given a serious of questions that I am have trouble interpreting, the questions are:
4.
Modify the constructor of Exercise 3 so that it assigns a new ID number as each variable is established. The ID number should be output to the screen.
**Please Note: Exercise 3 was just adding a Class constructor to the class structure - and basically setting all the class private member variables to '0' within that added constructor.
5.
Add constructors to the class of exercise 4. They should output the ID number when they are invoked.
6.
Write a constructor whose argument is an ID number. Overload it with the constructor of(Exercise 5) and then Write a main program to test this new constructor.
**So the questions: 4 and 5 are confusing me as they appear to be asking the same questions (i.e outputting the I.D numbers) and I need more than one 'constructor' in order to do this( I get that part).
**Question 6 Is effectively asking me to overload more than one instance declared of the class with an ID number as the argument!!!! I am confused because in my text book it specifically states that you cannot have an argument for a constructor when you have an array of classes declared within in the main program.
So if anyone can shed light on these questions and clarify how they would proceed I would appreciate the help. I appreciate that I may of interpreted the questions wrongly that is why I am asking for help.
**Please note: The name of the class: 'class classroom' is not ideal but it is what I copied from the text book question!
**Please also note that I have answered (I think!) exercise/question 4 by adding code that Id's each instance of the class variable.
And the relevant code relating to the above questions are:
#include <iostream>
#include <cstdio>
using namespace std;
class classroom{
char name[25];
int student_id;
float grades[10];
float average;
int num_tests;
float letter_grade;
**static int next_student_id;**
public:
void enter_name_id(void);
void enter_grade(void);
void average_grades(void);
void letter_grades(void);
void output_name_id_grade(void);
classroom();
};
**int classroom::next_student_id=1;**
and the constructor:
classroom::classroom(){
int i;
num_tests=0;
**student_id=next_student_id++;**
**cout<<"\nstudent id: "<<student_id;**
average=0.0;
for(i=0;i<10;i++){
grades[i]=0.0;
}
for(i=0;i<27;i++){
name[i]='-';
}
cout<<"\n*****************Finished*****************";
}
And the main program declaration:
int main()
{
classroom students[3];
//and so on...
}
and the code added for question/Exercise 4 was:
in the class structure I added the following private member variable:
**static int next_student_id;**
and outside of the class structure I initialized the static variable to 1
int classroom::next_student_id=1;
and in the constructor I added this code: which basically outputted to the screen a unique ID for each instance of classroom class variable:
student_id=next_student_id++;
** cout<<"\nstudent id: "<
Many thanks in advance
Questions 4 and 5 do appear to be the same from what you've provided - I'd reread it carefully to be sure, but it wouldn't be the first time textbook examples had a typo (in fact, I've run across that many times - alot of book companies are lazy when it comes to the exercises).
You do have the right answer with your static counter, so I wouldn't worry about it - you've understood the goal and solved the problem.
Question 6... it sounds like it wants you to just add an extra constructor to the class - so, you would have the default constructor (which you must explicitly write, but you already have done this in order to do your static counter), and you would also have a one-parameter constructor taking an integer. The one-parameter constructor should not need to use the static variable as it is allowing the user to provide the id to the class explicitly.
Moving on (since I think you've already got all of this), you are also correct in thinking that you can't provide an argument to a constructor when making an array. To test #6 as it suggests, you'll either have to make a stand-alone object (i.e. not an array), or something like a std::vector or other container that provides this capability.
#include <iostream>
#include <vector>
class A {
public:
A(int i) { /* Empty */ }
};
int main()
{
//Creates a new vector holding 5 A's initialized with the 2nd parameter.
std::vector<A> myVec(5, A(7));
}
Note that this technically creates a temporary A which is used to initialize the 5 vector entries. Also note that a std::vector is part of the STL (standard library), and it is basically a dynamically sized array.
Where, point 6, requires to have an array of class objects?
int main()
{
classroom studentA(100);
classroom studentB();
classroom studentC(200);
classroom studentD();
classroom students[100];
//and so on...
}

how to dynamically create methods to operate on class objects initialized at runtime

I have a class, say
class AddElement{
int a,b,c;
}
With methods to set/get a,b,c... My question is definitely a logic question - say I implement AddElement as follows:
int Value=1;
Value+=AddElement.get_a()+AddElement.get_b()+AddElement.get_b();
Now imagine I want to do the above except 'a,b,c' are now arrays, and instead of 'adding' I do scalar addition. At runtime sometimes I need 'a' but not 'b' or 'c', so I could rewrite as:
Value+=AddElement.get_a();
(Of course the += is overloaded to represent a scalar addition... and Value is the same size as a) - Other times I might only need b or c to be added etc...
Is there a way to go about selecting which elements, a,b,c, I want to initialize and later use at runtime? ( i.e. I don't want to malloc a huge array if I'm not going to use it).
In the end I need a class that has a,b,c and then methods that can operate on any combination of a,b, or c - having the user define what methods they need at runtime (via some kind of flag, or config file).
Currently I'm doing the following:
Value+=AddElement.get_a()*FlagA+AddElement.get_b()*FlagB+AddElement.get_c()*FlagC;
where FlagA=1 if you want to use 'a' in the addition or 0 if you don't want it to be included (The same for FlagB and FlagC). This is costly if the array 'a' is very large.
I'm probably just not thinking hard enough, but this problem has been bothering me. If you need me to better define the issue I will try, but I believe this is enough to get my point across.
Edit 2
I also forgot to add that I can't use any conditionals during the implementation of the addition (this is going to be used in a CUDA kernel and I can't have any thread diverngance - I was hoping to avoid mentioning CUDA since this is entirely a c++ question)
Edit 3
I believe what I need to do is use virtual functions. I want to call the function in the same manner, except have it execute a case specific function.
Edit 4
I would appreciate if someone took a look at my solution - maybe its too 'exotic' and there's a simpler method to accomplish the same end. Thanks for all the suggestions!
Edit 5
Thanks to another user I looked at the Strategic Design Pattern - and this is exactly the solution I used for this problem. I had never heard of that before and ended up rethinking a problem that has already been done (took a while for someone to mention something about it). So the solution:
Determine Algorithm at Runtime = Strategic Design Pattern.
You provide your class with a method GetSumOfActiveElements that does just what the name says. You can make this class virtual and create subclasses for each scenario, or have the class manage the memory efficiently in some other way.
What about something like this?
vector<pair<int, bool>> values(3);
values[0].first = 1;
values[0].second = false;
values[1].first = 2;
values[1].second = true;
values[2].first = 3;
values[2].second = false;
int sum = values[0].first * values[0].second +
values[1].first * values[1].second +
values[2].first * values[2].second;
You could probably make this cleaner/extensible using functors and <algorithm>.
It's not clear to me why conditionals are a bad thing - multiplication will be more expensive I would think. Is this a CUDA limitation or idiosyncracy?
If you allowed conditionals you could make your vector member a class that encapsulated a value and an in-use flag, and use filtering algorithms to perform aggregation as required.
Does this rough outline of code work for you?
struct S{
int getx() {return 0;}
int gety() {return 0;}
int getz() {return 0;}
};
int main(){
int (S::*p[3])(); // allocate as per need
p[0] = &S::getx; // populate as per need at run time
p[1] = &S::gety;
p[2] = 0;
int val = 1;
S obj;
int nCount = 0;
while(p[nCount] != 0)
val += (obj.*(p[nCount++]))();
}
EDIT 2: #Steve Townsend: That's right. I missed that conditional stuff.
How about this.
struct S{
int getx() {return 0;}
int gety() {return 0;}
int getz() {return 0;}
S(){}
S(S &obj, int (S::*p)()){
val += (obj.*p)();
}
static int val;
};
int S::val = 0;
int main(){
S obj;
S buf[] = {S(obj, &S::getx), S(obj, &S::gety)}; // the magic happens here in
// the constructor
}
So I think I got it -
struct S{
int x,y;
bool needx,needy;
};
class AnyFunction {
protected:
S Vals;
int TotalValue;
public:
virtual void SetValues(void) =0;
virtual void AddValues(void) =0;
}
class ImplementationFunc1 : public AnyFunction {
public:
void SetValues(S * Vals) { S.x=Vals->xval; }
void AddValues(void){ TotalValue+=Vals->x; }
}
class ImplementationFunc2 : public AnyFunction {
public:
void SetValues(S * Vals) {S.x=Vals->xval;S.y=Vals->yval;}
void AddValues(void){ TotalValue+=(Vals->x+Vals->y); }
}
int main(){
S SVals;
AnyFunction * APointerToAnyFunction;
// read a file that says if we need either x or y
SVals.needx=true; // (i.e. read from file)
SVals.needy=false; // (read from file)
if(Svals.needx){
SVals.x=Xfromfile;
if (Svals.needy){
ImplementationFunc2 Imp1;
SVals.y=yfromfile;
APointerToAnyFunction=&Imp1;
}
else{
ImplementationFunc1 Imp2;
APointerToAnyFunction=&Imp2;
}
}
...
// blah set some values
...
// So now I can call the function the same way (i.e. the call is always the same, no matter what kind of addition it needs to do), but I have all
// the logic for the conditions done _outside_ the addition
APointerToAnyFunction->AddValues();
So that should basically do it! no I can use the call: "APointerToAnyFunction->AddValues()" To perform the addition. The implementation can be determined by flags at the beginning of the program, then I can write a different class for each condition that i need to satisfy, and then have my polymorphic class inherit the properties of the base class.
Sorry if I did not fully define my problem, or the statement was vague - I didn't really know exactly how to do what I was explaining, but knew it was possible. Is this the right way to go about this? Is there a more efficient way?
Thanks to all who responded. Of course when x and y are arrays, I dynamically allocate x and y when necessary...
How about a std::vector of elements?
Problem spec is a bit unclear, to say the least, but I think that would work for you.
Cheers & hth.,