I am attempting to learn C++ (currently only know PHP and some C#) and have run into my first issue.
I am trying to call a class inside a switch, then use that defined variable after the switch. However, I get the error described in the title.
#include <iostream>
#include <string>
using namespace std;
class Hero {
protected:
int hHealth,hStamina,hExp;
string hName;
public:
void Create(string);
string GetName() {
return this->hName;
}
};
class Wizard:public Hero {
public:
void SetStats(string hName) {
this->hName = hName;
this->hHealth = 40;
this->hStamina = 80;
}
};
int main() {
string hName;
int hClass;
cout << "Welcome to Ryan's Dungeons & Dragons Adventure!\n\n";
cout << "Enter your Heroes name\n";
cout << "Name: ";
cin >> hName;
cout << hName << ", please select your class\n";
cout << "(1) The Wizard\n";
cout << "(2) The Warrior\n";
cout << "(3) The Rogue\n";
cout << "(4) The Priest\n";
cout << "Class: ";
cin >> hClass;
switch (hClass) {
case 1:
Wizard _hero;
break;
}
cout << _hero->GetName();
system("PAUSE");
return 0;
}
The error in question occurs on the line:
cout << _hero->getName();
where it says _hero is undefind.
_hero is defined only within the scope of that switch statement. You need to create objects in the same or higher up scope that you'll be using them.
One way you can get around this is define a pointer to Hero before the switch (initializing to null) and then set it to a value inside the switch. For instance:
Wizard *_hero = NULL;
switch (hClass) {
case 1:
_hero = new Wizard();
break;
}
}
if (_hero) {
cout << _hero->GetName();
}
You're also using the -> on a class value (as opposed to a pointer to one). Scope issues aside, you probably intended to write _hero.GetName(). Inside your class, -> is right however since this is a pointer to your object.
switch (hClass) {
case 1:
Wizard _hero;
break;
} // <-- _hero is deallocated at this point
cout << _hero->GetName();
The scope of _hero is limited to the switch statement.
I don't think that even works in C#... what you want is a pointer that's going to be initialized in the switch statement:
Hero* _hero = 0;
switch(hClass){
case 1: _hero = new Wizard;
break;
}
// use _hero ...
// at the end, delete it
delete _hero;
Though, you now most likely need a virtual destructor and virtual functions. Read up on them, they're a powerful OO feature. But you probably know about them from C#.
You said you know some C# and php, which I do not. I just want to know how would this have behaved in C#.
Creating an object inside some scope and using it outside the scope. Like: {int a;} a = 0;
In C++ its an issue.
switch (hClass) {
case 1:
Wizard _hero;
break;
}
//At this no _hero is present. _hero is out of its scope
The _hero object is restricted to the scope of that switch block. What you want is probably this:
Hero* _hero;
switch (hClass) {
case 1:
_hero = new Wizard();
break;
}
cout << _hero->GetName();
Related
I'm required to work with multiple classes in one .cpp file. I'm not sure what I'm doing wrong, is there a header file I need to include?
These are the errors I'm getting:
error C3646: 'loginObject': unknown override specifier
error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
error C2065: 'loginObject': undeclared identifier
#include <iostream>
#include <string>
using namespace std;
//Declaration of Class that Allows User to Select a Menu Option
class Menu
{
private:
int userChoice = 0; //User's Menu Selection
//Class Objects
Login loginObject;
public:
void options()
{
//Loop of Initial Menu
do
{
//Startup Menu
cout << "\n\tMain Menu:"
"\n\n\t1. Login"
"\n\t2. Create Password"
"\n\t3. Change Password"
"\n\t4. Delete User"
"\n\t5. Exit"
"\n\nSelection: ";
cin >> userChoice;
cout << endl;
//Switch Statement that Determines Course of Action based upon User's Choice
switch (userChoice)
{
case 1:
loginObject.login(); //Option to Login
break;
case 2:
cout << "\nCreating Password..."; //Option to Create a New Password
cout << endl;
break;
case 3:
cout << "Changing Password..."; //Option to Change an Old Password
cout << endl;
break;
case 4:
cout << "Deleting User..."; //Option to Delete a User
cout << endl;
break;
case 5:
cout << "Exiting..."; //Option to Exit the Program
cout << endl << endl;
system("pause");
default:
cout << "INVALID MENU OPTION!\n";
break;
}
} while (userChoice != 5); //Loop to Return to Initial Menu
}
};
//Declaration of Class that Manages all Activities Dealing with Login
class Login
{
private:
public:
void login()
{
cout << "\nLogging In...";
cout << endl;
}
};
//Main File
int main()
{
//Call to Menu Class
Menu menuVariable;
menuVariable.options();
return 0;
}
Generally speaking, your C++ code is read from top to bottom. So you can't use the name Login before it's defined. In your case, you can just move Login to above Menu (since the former does not depend on the latter) and it'll all be fine. In general, you can write a prototype at the top of your file to indicate the shape of a class without showing its implementation. So, for Login, that would be
class Login {
public:
void login(); // Note: No function body
};
The idea is to display all the data from the collected from the user in a tabular format according to the structures and enumerations defined. I've gotten some warnings about the use of the switch statement but the most inhibiting thing seems to be the use of the "s.width" when attempting to display the values. When I attempt to compile it advises that it's expecting a semicolon before s in s.width and it continues to move the semicolon to the next value. Is there something incorrect about the way I am referencing the values from my enumerations?
#include <iostream>
#include <string>
#include <iomanip>
using namespace std;
//TODO 1: ShapeKind Enumeration goes here
enum class ShapeKind{
CIRCLE,SQUARE,RECTANGLE
};
//TODO 2: Shape Structure goes here
struct Shape{
ShapeKind kind;
double length, width;
};
// Function prototypes and definitions
double area(Shape s);
//TODO 3: area() definition goes here
double area(Shape s){
double a;
switch(s.kind){
case ShapeKind::CIRCLE:
return a= (s.length * s.width * 3.14) /4 ;
case ShapeKind::SQUARE:
return a = s.length *s.length;
case ShapeKind::RECTANGLE:
return a = s.length * s.width;
}
}
double perimeter(Shape s);
//TODO 4: perimeter() definition goes here
double perimeter(Shape s){
double p;
switch(s.kind){
case ShapeKind::CIRCLE:
return p= s.length * 3.14;
case ShapeKind::SQUARE:
return p = s.length *4;
case ShapeKind::RECTANGLE:
return p = 2 *(s.length + s.width);
}
}
string nameOf(Shape s);
//TODO 5: nameOf() definition goes here
string nameof(Shape s){
switch(s.kind){
case ShapeKind::CIRCLE:
return "Circle";
case ShapeKind::SQUARE:
return "Square";
case ShapeKind::RECTANGLE:
return "Rectangle";
}
}
void promptAndReadInputFor(Shape& shape);
//TODO 6: promptAndReadInputFor() definition goes here
void promptAndReadInputFor(Shape& s){
switch(s.kind){
case ShapeKind::CIRCLE:
cout <<"Enter the diameter or a circle: "<< endl;
cin >> s.length;
s.width =s.length;
case ShapeKind::SQUARE:
cout << "Enter the length of one side: "<< endl;
cin >>s.length;
s.width=s.length;
case ShapeKind::RECTANGLE:
cout << "Enter the length and width: "<< endl;
cin >>s.length>>s.width;
if (s.length == s.width)
{
s.kind = ShapeKind::SQUARE;
}
}
};
// The main function
int main() {
// Shape objects
Shape circle = { ShapeKind::CIRCLE, 0, 0 };
//TODO 7: define two more shape objects: a square and and a rectangle
Shape square= {ShapeKind::SQUARE, 0, 0};
Shape rectangle ={ShapeKind::RECTANGLE, 0, 0};
//TODO 8: Call the promptAndReadInputFor() function on each of the above three shapes
promptAndReadInputFor(circle);
promptAndReadInputFor(square);
promptAndReadInputFor(rectangle);
//TODO 9: Print a out a report of these shapes in a table-like format
cout << setw(4) << "Shape" << setw(4) << "Width" << setw(4) << "Height" << setw(4) << "Perimeter"<< setw(4) << "Area"<<endl;
cout << setw(4) << nameOf(circle) << setw(4) s.width << setw(4) s.length << setw(4) perimeter(circle)<< setw(4) << area(circle)<< endl;
return 0;
}
You are missing a <<
cout << setw(4) << nameOf(circle) << setw(4) s.width << setw(4) s.length
// ^HERE there should probably be '<<'
<< setw(4) perimeter(circle)<< setw(4) << area(circle)<< endl;
In your code, your function declaration of nameOf and definition nameof are different;
should be same
string nameOf(Shape s);
string nameof(Shape s) {} // not the same in your code
and one more change needed,
you have not declared any local s variable inside main, you are declared as circle your Shape object.
Fixed all the bugs. Wanna thank you for your help and also pass on some info for anyone that might need help with something similar. My promptAndReadInputFor function was missing a return statement for each case which caused the function to never end. Both answers I received were correct as the references made for "s.width, s.etc" weren't applicable within the scope of the main function so changing them to "circle, square, etc" which were the objects created to be used solved the issue. I appreciate the assistance you guys provided. Felt great to finally solve this problem.
I am a beginner with c++ and I'm having trouble with this error, I am aware that this error means I am trying to use a variable that hasn't been given a value yet.
The context of the program is a that the variable is called option, the value of option is input by the user in a later function. When I started getting this error my only thought was to give the variable a value that was determined in the function so written as "option = enteroption(option);" however it still says the variable is uninitialized. can anybody help explain what I am maybe doing wrong? thanks.
#include "pch.h"
#include <iostream>
#include "Arcade game menu.h"
using namespace std;
int main()
{
char option; //declare variable
float balance; //declare variable
const unsigned char pounds(156); //signatures for functions
void processoption(char, float&, char);
void payinitialfee(float&);
char enteroption(char);
payinitialfee(balance); //call functions
enteroption(option);
while ((option != 'Q') && (balance > 0)); //while option is not Q and balance is greater than 0 call functions
{
processoption(option, balance, pounds);
option = enteroption(option);
}
cout << "Thanks for playing." << endl;
system("pause");
}
void payinitialfee(float& balance)
{
balance = 100;
}
char enteroption(char option)
{
cout << "Enter option..." << endl << "P:Play or B:Balance or Q:Quit" << endl;
cin >> option;
void putinUpperCase(char);
putinUpperCase(option);
return option;
}
void putinUpperCase(char option)
{
option = toupper(option);
}
void processoption(char option, float&balance, char pounds)
{
void playGame(float&); //signatures
void showbalance(float&, char);
switch (option)
{
case 'P': playGame(balance);
break;
case 'B': showbalance(balance, pounds);
break;
default: cout << "ERROR: INVALID COMMAND." << endl;
break;
}
}
void playGame(float& balance)
{
cout << "Playing..." << endl;
balance = balance - 20;
}
void showbalance(float&balance, char pounds)
{
cout << "The current balance is... " << pounds << balance << endl;
}
You are passing the uninitialized variable option to the function enteroption as an argument
option = enteroption(option);
This does not make any sense and the compiler points this to your.
The function can be declared like
char enteroption();
Within the function you can declare a local variable option that will get a value. Then this variable can be returned from the function and is assigned to the variable option declared in main.
Also it seems that the call of the function
putinUpperCase(option);
has no effect because the variable option is not passed be reference. See the function declaration
void putinUpperCase(char);
It seems the function should be declared like
void putinUpperCase( char & );
The compiler is right about this.
In you current code you call option = enteroption(option). At this point option is undefined, which the compiler tells you. You either want to pass option by reference:
void enteroption(char &option)
{
// ...
cin >> option;
// ...
}
Or don't use a parameter here:
char enteroption()
{
char option;
// ...
cin >> option;
// ...
return option;
}
You can pass the reference of local member option from calling function instead of returning a character. The same can be applied to make upper case letter which will ultimately called function can modify the value of the argument by using its reference passed in.
enteroption(option);
void enteroption(char& option)
{
cout << "Enter option..." << endl << "P:Play or B:Balance or Q:Quit" << endl;
cin >> option;
void putinUpperCase(char&);
putinUpperCase(option);
return;
}
void putinUpperCase(char& option)
{
option = toupper(option);
}
I am having a problem, where I need to declare an object for a class based on user input. The problem is that the scope of the object is stuck in the switch statement, and I was wondering if there was a way to make it public.
//ask the user to choose the class of the first fighter
cout << "Welcome to the fighting arena! Would you like the first competitor to be a FIGHTER <1>, a WIZARD <2>, a ROGUE <3>, or a RANGER <4>?" << endl;
cin >> competitor1;
cout << "And what is the name of the competitor?" << endl;
cin >> name1;
//creates an object in the appropriate class and initializes it
switch (competitor1)
{
case 1:
{
Fighter Battler1(name1);
break;
}
case 2:
{
Wizard Battler1(name1);
break;
}
case 3:
{
Rogue Battler1(name1);
break;
}
case 4:
{
Ranger Battler1(name1);
break;
}
default:
cout << "Sorry please enter a valid number!" <<endl << endl;
break;
}
cout << Battler1.hp //this is undefined because of the scope
Yes everything is written inside the main fuction, I know the probelm is scope and just need a way to get around it.
I wouldn't use a switch case at all here, instead, an array of functors, that each create a different type of fighter and return a pointer to their base, i.e.
template<typename T>
std::unique_ptr<Champion> Create( ) { return std::make_unique<T>( ); }
std::function<std::unique_ptr<Champion>(void)> createFunctions [] = {
Create<Fighter>
,Create<Rogue>
,Create<Wizard>
,Create<Ranger>
};
Usage:
std::cin >> competitor1;
std::unique_ptr<Champion> Battler1 = createFunctions[competitor1];
std::cout << Battler1->hp;
You cannot do it as you described. You will need some kind of polymorphism: an object that will change it's behavior depending on it's type.
The most straightforward way to do it would be to use a variant:
using Battler = std::variant<Fighter, Wizard, Rogue, Ranger>;
auto battler1 = [&]() -> std::optional<Battler> {
switch (competitor1)
{
case 1:
return Fighter{name1};
case 2:
return Wizard{name1};
case 3:
return Rogue{name1};
case 4:
return Ranger{name1};
default:
cout <<"Sorry please enter a valid number!" << endl;
return std::nullopt;
}
}();
// if a valid number has been chose.
if (battler1) {
cout << std::visit([](auto& battler) { return battler.hp; }, *battler1);
}
Note that you need an up to date compiler, or using boost::variant instead. This solution might also not be the most scalable as you'll need to effectively update the Battler alias when adding a new battler type.
Also, you could use polymorphism through pointers and vtables. It require more changes to your program, but might be more appropriate in some cases:
struct Battler {
virtual int getHp() const = 0;
virtual ~Battler() = default;
};
struct Fighter : Battler {
int getHp() const override {
return hp;
}
};
struct Wizard : Battler {
int getHp() const override {
return hp;
}
};
// ... all other classes of Battler
Then, change you switch case accordingly:
std::unique_ptr<Battler> battler1;
switch (competitor1)
{
case 1:
battler1 = std::make_unique<Fighter>(name1);
break;
case 2:
battler1 = std::make_unique<Wizard>(name1);
break;
case 3:
battler1 = std::make_unique<Rogue>(name1);
break;
case 4:
battler1 = std::make_unique<Ranger>(name1);
break;
default:
cout << "Sorry please enter a valid number!" <<endl << endl;
break;
}
// if a valid number has been chose
if (battler1) {
cout << battler1->getHp();
}
If you could make the object (Battler1) global, what datatype would it be? Instance of class Fighter, Wizard, Rogue or Ranger?
The solution to your problem is this: Create a parent class (let's say, Character) from which all the others (Fighter...) will inherit: class Fighter : Character etc. And then, create the objects dynamically:
Character *battler;
switch (...) {
case 1:
battler = new Fighter(name);
break;
case 2:
battler = new Wizard(name);
break;
}
// don't forget to free the memory when not needed anymore
delete battler;
Hello I work on a project for university which has to contain classes.
I can't paste them here because it would take a lot to read hundreds of rows, but I have a class USER which works perfectly, but I also have a MainMenu() function written right before main(),which is the only one I call in main(), made with switch, which is supposed to redirect the console to classes' submenus or to show objects for every class, it depends on class.
Ok, from this MainMenu when I choose to go to Users List option, I want the console to show me the list of users, that means, all user class objects I created in main(). I thought of creating a new function with reference to class, but I don't know how to use it in this situation when I don't call it in main, and however i need to reffer to all objects in that class not to mention a specific object..
How can I do this because I only call that MainMenu() in main(), not write it here to be able to use the objects directly?
Be kind to me, I'm a beginner and I never dealt with this type of requisites. I would be grateful if you could help me solve this.
Have a nice day.
#include<iostream>
using namespace std;
class user{};
class B{};
class C{};
void MainMenu()
{
cout << " Main Menu" << endl;
cout << endl;
int chosenoption;
cout << "1.Users List" << endl;
cout << "2.Class B Submenu" << endl;
cout << "3.Class C submenu" << endl;
cout << "Type here the number of the option you want to choose: ";
cin >> chosenoption;
system("pause");
switch (chosenoption)
{
case 1:
system("cls");
cout << "There should be shown the list of users, here the only users i created in main are u1 and u2, and i need to make them and their attributes appear in this screen" << endl;
break;
case 2:
system("cls");
ClassBSubmenu();
break;
case 3:
system("cls");
ClassCSubMenu();
break;
default:
cout << endl;
cout << "Choose one of the available options only!" << endl;
cout << "Type here: " << endl;
}
}
void main()
{
User u1(...);
User u2(..);
}
ClassBSubmenu and ClassCSubmenu are functions created before MainMenu, but I haven't edited them too much
You might want to have an array of Users which you pass to the MainMenu() function.
User u[] = { User(...), User(..) };
When you pass an array, you are actually passing a pointer to the first element in the array, so the Users could be modified in MainMenu() and the changes would exist in main().
void MainMenu( User users[] )
{
...
users[0]
MainMenu( u );