C++ constructor variable values at runtime will not be overridden [closed] - c++

Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 4 years ago.
Improve this question
I am following a c++ course with Unity. I followed the instructor, but I halted at the part where he defines a constructor. For some reason the variables will not be overridden at runtime with the values I gave in the definition of my constructor.
Here is my code:
FBullCowGame.h
#pragma once
//#include <iostream>
#include <string>
class FBullCowGame {
public:
FBullCowGame();
void Reset() const; //TODO make a more rich return value
int GetMaxTries() const;
int GetCurrentTry() const;
bool CheckGuessValidity(std::string) const;
bool IsGameWon() const;
private:
int MyCurrentTry;
int MyMaxTries;
};
FBullCowGame.cpp
#include "FBullCowGame.h"
//#pragma region constructors
FBullCowGame::FBullCowGame() {
int MyCurrentTry = 666;
int MyMaxTries = 666;
}
//#pragma endregion
//#pragma region getters
void FBullCowGame::Reset() const { return; }
int FBullCowGame::GetMaxTries() const { return MyMaxTries; }
int FBullCowGame::GetCurrentTry() const { return MyCurrentTry; }
bool FBullCowGame::CheckGuessValidity(std::string) const { return false; }
bool FBullCowGame::IsGameWon() const { return false; }
//#pragma endregion
main.cpp
#include <iostream>
#include <string>
#include "FBullCowGame.h"
void PrintIntro();
void PlayGame();
std::string GetGuess();
bool AskToPlayAgain();
FBullCowGame BCGame;
int main() {
std::cout << BCGame.GetCurrentTry();
std::cout << BCGame.GetMaxTries();
bool bPlayAgain = false;
do {
PrintIntro();
PlayGame();
bPlayAgain = AskToPlayAgain();
} while (bPlayAgain);
return 0;
}
void PlayGame() {
int MaxTries = BCGame.GetMaxTries();
std::cout << MaxTries << "\n";
for (int i = 1; i <= MaxTries; i++) {
std::string Guess = GetGuess();
std::cout << "Your guess was: " << Guess << std::endl;
std::cout << std::endl;
}
}
void PrintIntro() {
constexpr int WORD_LENGTH = 9;
std::cout << "Welcome to Bulls and Cows, a fun word game.\n";
std::cout << "Can you guess the " << WORD_LENGTH;
std::cout << " letter isogram I'm thinking of?\n\n";
return;
}
//std::cout << "Your guess is: " << Guess << "\n\n";
std::string GetGuess() {
int CurrentTry = BCGame.GetCurrentTry();
std::string Guess = "";
std::cout << "Try " << CurrentTry << ". Enter your guess: ";
std::getline(std::cin, Guess);
return Guess;
}
bool AskToPlayAgain() {
std::cout << "Do you want to play again(y/n)? ";
std::string Response = "";
std::getline(std::cin, Response);
//std::cout << "First char is: " << ((Response[0] == 'y') || (Response[0] == 'Y')) << "\n";
return (Response[0] == 'y') || (Response[0] == 'Y');
}
I a outputting the values with these two lines inside main:
std::cout << BCGame.GetCurrentTry();
std::cout << BCGame.GetMaxTries();
I only get 0 for both values from the getter functions. I am a beginner in c++ and I need a bit of help. I was thinking it's an IDE problem, so I cleaned the solution, rebuilt, rerun, restarted the IDE and did that again. Any kind of help is appreciated. Thanks.

In your class declaration you have:
{
...
private:
int MyCurrentTry;
int MyMaxTries;
};
Then in your constructor you think you are initializing them with this:
FBullCowGame::FBullCowGame() {
int MyCurrentTry = 666;
int MyMaxTries = 666;
}
But what is actually happening here is that you are creating local stack variables with the same exact name as your class's members. Your class member variables can be seen by using the class's this pointer ->:
{
this->MyCurrentTry ...
this->MyMaxTries ...
}
as these two sets of variables are not the same. Your member variables are not even being initialized; the compiler might be smart enough to automatically initialize them with 0 but this isn't guaranteed as they can have any arbitrary value. You are only declaring and initializing stack variables that are local to the constructor only.
To fix this you have 3 options.
First it was already mentioned in the comments. Just remove the type int before the names in the constructor so that you are not declaring local variables but are actually using the members as such:
{
MyCurrentTry = 666;
MyMaxTries = 666;
}
The second option is to do the same but to use the class's this pointer ->
{
this->MyCurrentTry = 666;
this->MyMaxTries = 666;
}
The third and more preferred method is to use the class constructor's member initializer list.
FBullCowGame::FBullCowGame() :
MyCurrentTry( 666 ),
MyMaxTries( 666 ) {
}
This should explain what you was doing wrong within your class's constructor and why the variables were not being initialized to what you thought they should of been, and why you was getting the output you was seeing.
A side note; your class's Reset() function does absolutely nothing.
If you want to use it as you are thinking then you would want it to look like this:
// Remove the const qualifier; otherwise you will not able to modify
// the class's members with this function. "const" is usually good for
// methods that return a member that does not make any internal changes
// to the member or the class.
{
public:
void Reset();
};
FBullCowGame::Reset() {
MyCurrentTry = "whatever value to reset it to."
MyMaxTries = "whatever value to reset it to."
}

Related

Copy constructors & Dynamic Memory C++ [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 23 days ago.
Improve this question
Recently I've started working on my first OOP project and after having written the program I am trying to optimize it for code efficiency. I want to place the parts of the program that are being copied a lot on the heap.
I can't understand why in certain places objects are copied.
An example:
In the main.cpp movies object, which stories movie objects, is created. Add_movie function is called that checks if the movie we are trying to add has already been added, if not, we create a temp object, initialize its private members to the argument values being passed, append it to the vector of the movies object. A copy constructor would be called when movie object is being appended to the vector. WHY? I can't understand the part WHY is it being copied? Is it because of the scope???
If there was an object initialized in the main like
Movie movie1{arguments};
and other movie is created based on movie1
Movie movie2{movie1}.
It makes sense to me, but in the example I gave, it doesn't make sense to me at all
The example of the function I am referring to
bool Movies::add_movie(std::string name, std::string rating, int watched)
{
for (const Movie& obj : movies_list)
{
if (obj.get_name() == name) // search for a match
{
return false; // if found stop executing
}
}
Movie temp{ name, rating, watched }; // creates a new object and initializes its private members to the passed arguments
# movies_list.push_back(temp); // appends the object to the vector
# *** return true;
}
I don't know if it will help, but there is the code of the program
**main.cpp **
#include "Movie.h"
#include "Movies.h"
#include <iostream>
#include <string>
void add_movie(Movies& obj, std::string name, std::string rating, int watched)
{
if (obj.add_movie(name, rating, watched))
{
std::cout << name << " succesfully added" << std::endl;
}
else
{
std::cout << name << " already has been added" << std::endl;
}
}
// if the parent increment_watched function returns true, inform the user about the result of the operation
void increment_watched(Movies &obj, std::string name)
{
if (obj.increment_watched(name)) // if Movies::increment_watched returns
{
std::cout << name << " watch count succesfully incremented by 1" << std::endl;
}
else {
std::cout << name << " movie not found" << std::endl;
}
}
int main()
{
Movies list;
add_movie(list, "Fight Club", "A", 1);
add_movie(list, "Fight Club", "A", 1);
add_movie(list, "Inception", "A", 1);
increment_watched(list, "Fight Club");
increment_watched(list, "Else Test");
list.display();
return 0;
}
movies.cpp
#include "Movie.h"
#include "Movies.h"
#include <iostream>
bool Movies::add_movie(std::string name, std::string rating, int watched)
{
for (const Movie& obj : movies_list)
{
if (obj.get_name() == name) // search for a match
{
return false; // if found stop executing
}
}
Movie temp{ name, rating, watched }; // creates a new object and initializes its private members to the passed arguments
movies_list.push_back(temp); // appends the object to the vector
return true;
}
void Movies::display() const
{
if (movies_list.size() == 0) // checks the vector size
{
std::cout << "The list is empty" << std::endl;
}
else
{
std::cout << "\nThe list of the movies: " << std::endl;
std::cout << "----------------------------" << std::endl;
for (const Movie& obj : movies_list)
{
obj.display_members(); // accesses the private members of the object that are stored in the vector and outputs them to the user
}
}
}
bool Movies::increment_watched(std::string name)
{
for (Movie &obj : movies_list) // iterates through the movie objects until finds the match in name
{
if (obj.get_name() == name)
{
obj.increment_watched(); // increments watched by 1
return true;
}
}
return false;
}
movie.cpp
#include <string>
#include <iostream>
#include "Movie.h"
// constructor for initializing private members of the object
Movie::Movie(std::string name, std::string rating, int watched)
{
this->name = name;
this->rating = rating;
this->watched = watched;
}
// get methods
std::string Movie::get_name() const { return name; }
std::string Movie::get_rating() const { return rating; }
int Movie::get_watched() const { return watched; }
// display private members
void Movie::display_members() const
{
std::cout << "Name: " << get_name() << std::endl;
std::cout << "Rating: " << get_rating() << std::endl;
std::cout << "Times watched: " << get_watched() << std::endl;
std::cout << "\n" << std::endl;
}
// setter function
void Movie::increment_watched() {watched++;}
// DEBUGGING
Movie::Movie(const Movie &obj):name{obj.name}, rating{obj.rating}, watched{obj.watched} {std::cout << "copy constructor called for " << name << std::endl;}
Movie::~Movie() {std::cout << "destructor called for movie " << name << std::endl;}
Debugging the program for hours to see which parts are being copied, when copied, when destructed to get a better grasp.
Watching countless videos that explain the lifetime of the objects, copy constructors, destructors, but it still doesn't make sense for me!
push_back() takes an object and appends it at the end of the vector. It has to make a copy because it must keep the original object intact because you might need it later. If you want to avoid the copy, you’d have you use std::move to trigger the move constructor.
movies_list.push_back(std::move(temp));
However, in your example you basically want to construct an object at the end of the vector. emplace_back is just what you need; no copying or moving, just pass the constructor arguments.
movies_list.emplace_back(name, rating,watched);

Use Variable from Another Function in C++

I would like to take the return value from the function on the top and then do something with it in the function on the bottom. What should I put in the bottom function to use the value that was returned from "loadVectorWithReturn"
I do realize that I could create a new variable and store it there for later recall but I am trying to do more complicated things now.
Thank you
double vectors1::loadVectorWithReturn() {
vectors1 v1;
for (int i = 0; i <= 10; i++) {
v1.value.push_back(i);
cout << v1.value[i] << ", ";
}
cout << endl;
cout << v1.value[5] << endl;
return v1.value[5];
}
double doSomethingWithVectorReturn(TAKE IN VALUE FROM loadVectorWithReturn) {
//do something with v1.value[5];
}
If you are saying, "I don't want to make a global variable for v1", you could do this.
double vectors1::loadVectorWithReturn() {
vectors1 v1;
for (int i = 0; i <= 10; i++) {
v1.value.push_back(i);
cout << v1.value[i] << ", ";
}
cout << endl;
cout << v1.value[5] << endl;
return v1.value[5];
}
double vectors1::doSomethingWithVectorReturn() {
int returned = loadVectorWithReturn();
//Do something with returned.
}
Note: the "vectors1::" in front of "doSomethingWithVectorReturn" allows "doSomethingWithVectorReturn" to use the "loadVectorWithReturn" function.
Keep in mind that if you are only using the "returned" value one time (or multiple although that can be slower in many cases), you could skip setting the variable and just use "loadVectorWithReturn()" in place of it.
Example (Simply cout's the value):
double vectors1::doSomethingWithVectorReturn() {
cout << loadVectorWithReturn();
}
I am feeling like you are needing this because you will use loadVectorWithReturnlater within doSomethingWithVectorReturn in some point.
If this is the situation we can use:
#include <iostream>
#include <functional>
struct A
{
int fooA() const
{
return 5;
}
};
void doSomethingWithA( std::function<int()> foo )
{
std::cout << foo();
}
int main()
{
A a;
doSomethingWithA([a]()
{
return a.fooA();
});
}

Pointer Function return value of Struct in Class [duplicate]

This question already has answers here:
Can a local variable's memory be accessed outside its scope?
(20 answers)
Closed 7 years ago.
I have been attempting to create a function getLocation() that utilizes a pointer to return the value of the struct Location declared in the Character class. I was curious as to the problem with my syntax (or my structure). Knowing that the asterisk * should refer to the value, why is it that my function using an ampersand string& Character::getInventory is able to return the value of that particular index (its return does not need to be converted)?
Trying Location& Character::getLocation() {return position; }
when run results in error C2679: binary '<<': no operator found
Nor
Location*
Which cannot be run as there is no conversion.
I read that the following is likely the most proper because it specifies the scope in which the structure resides, but still results in needing and returning a temporary.
Character::Location* const & Character::getLocation() {return &position; }
Any advice or input would be greatly appreciated, thanks in advance.
Below is my main.cpp, which of course will show the hexadecimal address for Location.
#include <iostream>
#include <string>
using std::cerr;
using std::cin;
using std::cout;
using std::endl;
using std::string;
class Character {
private:
string name;
string inventory[4];
public:
struct Location {
int x; int y;
};
Location position;
public:
void Character::setName(string x) { name = x; }
string Character::getName() { return name; }
void Character::setLocation(int x, int y) {
position.x = x; position.y = y;
}
Location* Character::getLocation() {return &position; }
void Character::setInventory(string(&x)[4]) { for (int i = 0; i < 4; ++i) { inventory[i] = x[i]; } }
string& Character::getInventory(int itemNumber) { return inventory[itemNumber]; }
};
void showUser(Character Character);
int main() {
try {
string items[4] = { "Sword", "Shield", "Potion", "Cloak" };
Character CharacterI;
CharacterI.setName("Some Character");
CharacterI.setInventory(items);
CharacterI.setLocation(1, 30);
cout << "\n" << "Retrieving Character Info..." << "\n" << endl;
showUser(CharacterI);
}
catch (std::exception & e) {
cerr << "\nError : " << e.what() << '\n';
}
system("pause");
return 0;
}
void showUser(Character character) {
cout << "Name : " << character.getName() << endl;
cout << "Location : " << character.getLocation() << endl;
for (int i = 0; i < 4; ++i) {
cout << "Inventory " << i + 1 << " : " << character.getInventory(i) << endl;
}
}
Ok, I think I understand the question better now. The reason why getInventory can successfully return a reference while getLocation does not is because getLocation returns a reference to a temporary variable, which is not good. See the link in #NathanOliver's comment for details. Additionally, to paraphrase a previous comment by #Peter Schneider, an * in an expression dereferences a pointer to return a value, while in a declaration it signifies that a variable will be of pointer type. The two usages are more or less opposites of each other. Example:
int* p = new int; //Declares a pointer to int
int x = *p; //Dereferences a pointer and returns an int
What you need to do is create a member variable to hold the Character's location, then set/get from that variable instead of creating temporaries. You did this already for name and inventory, just keep using that same pattern.
Additionally, whenever you use the Location struct outside of the Character class scope, you need to fully-qualify it with Character::Location.
Example:
#include <iostream>
using namespace std;
class Character {
public:
struct Location {
int x;
int y;
};
Location loc;
void SetLocation(int x, int y) {loc.x = x; loc.y = y;}
Location& GetLocation() {return loc;}
};
int main ()
{
Character c;
c.SetLocation(1,42);
Character::Location l = c.GetLocation();
cout << l.x << endl << l.y << endl;
return 0;
}
Output:
1
42

C++ Pointers In A Game

I am in what seems to be a never ending quest to understand pointers. I finally have a working code using pointers to create a quick character and enemy, then mock an overly simple battle. It works 100% as it seems, but I'm not 100% sure it's correct or what I did to make it right. I have read 13 chapters so far in my C++ book (2 being over pointers specifically), but I'm still not sure it's clicked. If this looks like a valid use and proper utilization of them, I think I'm getting there, just wanted some clarification if it is. Thanks in advance!
#include <iostream>
#include <string>
#ifndef CLASS_H
#define CLASS_H
class Unit
{
public:
Unit(const std::string name, int hp, int power);
~Unit();
void printHP();
void attack(Unit* unit);
bool isDead();
private:
std::string mName;
int mHP;
int mPower;
};
Unit::Unit(const std::string name, int hp, int power)
{
mName = name;
mHP = hp;
mPower = power;
}
void Unit::printHP()
{
std::cout << std::endl;
std::cout << mName << "'s HP: " << mHP << std::endl;
}
void Unit::attack(Unit* unit)
{
std::cout << std::endl;
std::cout << unit->mName << " takes " << this->mPower << " damage! " << std::endl;
unit->mHP -= this->mPower;
}
bool Unit::isDead()
{
return this->mHP < 1;
}
Unit::~Unit()
{
}
#endif
int main()
{
Unit player1("GoodFellow", 20, 5);
Unit Enemy("ABadMan", 10, 2);
while (!Enemy.isDead())
{
player1.printHP();
Enemy.printHP();
player1.attack(&Enemy);
Enemy.attack(&player1);
}
}
Modified it to this... I think I get the reason for only using a reference, just trying to get the concept of pointers....
#include <iostream>
#include <string>
#ifndef CLASS_H
#define CLASS_H
class Unit
{
public:
Unit(const std::string name, int hp, int power);
~Unit();
void printHP();
void attack(Unit& unit);
bool isDead();
void setHP(int hp);
private:
std::string mName;
int mHP;
int mPower;
};
Unit::Unit(const std::string name, int hp, int power)
{
mName = name;
mHP = hp;
mPower = power;
}
void Unit::printHP()
{
std::cout << std::endl;
std::cout << mName << "'s HP: " << mHP << std::endl;
}
void Unit::attack(Unit& unit)
{
std::cout << std::endl;
std::cout << unit.mName << " takes " << this->mPower << " damage! " << std::endl;
unit.mHP -= this->mPower;
}
bool Unit::isDead()
{
return this->mHP < 1;
}
void Unit::setHP(int hp)
{
this->mHP = hp;
}
Unit::~Unit()
{
}
#endif
int main()
{
Unit player1("GoodFellow", 20, 5);
Unit Enemy("ABadMan", 10, 2);
while (true)
{
while (!Enemy.isDead())
{
player1.printHP();
Enemy.printHP();
player1.attack(Enemy);
Enemy.attack(player1);
}
char playAgain;
std::cout << "Fight again? (y)/(n)" << std::endl;
std::cin >> playAgain;
if (playAgain == 'n')
{
break;
}
else
{
Enemy.setHP(10);
}
}
}
Yes, that's a reasonable use of pointers. I was actually glad to see that you used them very little. I was half expecting to see Unit* player1 = new Unit ... and such all over the place. But no, you used automatic storage duration all over (rather than dynamic), which was very appropriate.
So the main reason for passing Unit*s to the attack functions is to that inside the function you can modify the Unit that you're attacking and have the effect seen outside. If you were to pass the Units directly, they would be copied into the function and then the unit->mHP -= this->mPower; would only affect the copy.
However, there is a more appropriate tool at your disposal here. You can use references. A reference also allows you to pass an object without copying it, so that modifications inside the function can be seen outside. Your attack function signature would change to:
void Unit::attack(Unit& unit)
The type Unit& is a "reference to Unit". Don't confuse the use of & with taking the address of an object - it means something completely different here. You would then call it like so:
player1.attack(Enemy);
The point is you should try to avoid pointers as much as possible. Since you can use references here, which are safer (you do not need to check for null), you should use them.
It's fine to learn about how pointers to work, but in doing so, you should learn how to use other more appropriate tools for the job.

C++ Inheritance problem

I hope I got the relevant code in here. I have some problem when I want to fetch the menu option that I've added into to menu_1. I have this function on_select(int) that I use to fetch one sub-menu's options, which I do by using the display() function. But when I compile it will say that there are no function named display() in menu_option() class, which is the Base class, but what I want to is to access the display() function which is located in the sub_menu() class.
I have tried multiple thing to get the relevant object from the array without any success, so I'm here now asking for help with this one.
I have this following main()
#include <iostream>
using namespace std;
#include "menu.h"
int main()
{
sub_menu* main_menu = new sub_menu("Warehouse Store Menu");
sub_menu* menu_1 = new sub_menu("Menu1");
main_menu->add_option(new sub_menu("Menu2"));
main_menu->add_option(menu_1);
product_menu->add_option(new add_item("sub_item1"));
product_menu->add_option(new add_item("sub_item2"));
product_menu->add_option(new add_item("sub_item3"));
main_menu->display();
main_menu->on_select(1);
delete main_menu;
return 0;
}
header file
#include <iomanip>
#include <iostream>
#include <string>
using namespace std;
const int MAX_SIZE = 9;
class menu_option
{
public:
menu_option(string const& n) : title(n) {};
virtual ~menu_option();
virtual void on_select(int) = 0;
string get_title() { return title; }
protected:
string title;
};
/* ------------------------------------- */
class sub_menu : public menu_option
{
public:
sub_menu(string const& n)
: menu_option(n) { no_item = 0; }
~sub_menu() { delete[] list; };
void on_select(int);
void add_option(menu_option*);
void display();
private:
menu_option* list[MAX_SIZE]; //container for options in the sub_menu
int no_item;
};
implement file
void sub_menu::on_select(int i)
{
cout << (list[i])->get_title() << endl;
cout << (list[i])->display() << endl; //<------ Doesn't work
}
void sub_menu::add_option(menu_option* item)
{
list[no_item] = item;
no_item++;
}
void sub_menu::display()
{
cout << ">> " << get_title() << " <<"<< endl;
for( int i = 0; i < no_item; i++ )
{
cout << setw(2) << i << ": " << (list[i])->get_title() << endl;
}
}
You can do what you want to do, but it's bad. You have to cast down to sub_menu when you call display() in on_select(). Of course it's not going to work the way you have it, and the compiler is telling you exactly why.
The other option, which is probably better (though without a clear understanding of the problem space may not be the best) would be to add display() as a virtual function to the menu_option class.
To solve your immediate problem you'll want to use dynamic_cast to turn a menu_option* into a sub_menu*, like so:
sub_menu* submenu(dynamic_cast<sub_menu*>(list[i]));
Note that if the cast fails (i.e., the menu_option pointed to by list[i] is not a sub_menu after all) the value of the submenu pointer will be NULL, so make sure you check that it is a valid pointer before using it in subsequent code.