I have five files: class T, class M (an abstract class), class MC (a container), class AC (creates a particular object that is added into the MC container) and my Main file.
I have these functions to add an object (for this case, AC) and to retrieve a data member that you find in AC (a title).
The program compiles and it appears that I can create and add an AC object. However when I try to use my GetTitle function, the program crashes and I get the following error
“Unhandled exception at 0x00b938e6 in TLab 5.exe: 0xC0000005: Access
violation reading location 0xcccccce4.”
From what I looked up, this means I have a pointer that is bad/uninitialized. The only pointer in my program is this:
M *C[MCSize] //Found in MC.h
The constructor for MC looks like this:
MC::MC()
{
cout << "Enter Name: ";
getline(cin, CName);
cout << "Enter size of collection: ";
cin >> CurrentMCSize;
if (CurrentMCSize < 0 || CurrentMCSize > MCSize)
{
cout << "Size is invalid. Please re-enter: ";
cin >> CurrentMCSize;
}; //MCSize is defined in the header of MC.
The function to call the Title that is entered is here:
void MC::ListMTitles()
{
for (int i = 0; i < CurrentMCSize; i++)
{
cout << i << ". " << Collection[i]->GetTitle();
}
};
//GetTitle is defined in M.cpp
Where DMA occurs: //MC.cpp
void MC::AddM()
{
int Selection;
if(CurrentMCSize < MCSize)
{
DisplayMTypeMenu();
Selection = GetMTypeSelection();
switch(Selection)
{
case 1: Collection[CurrentMCSize] = new AC;
break;
// Other case statements
}
if (0 == Collection[CurrentMCSize])
{
cout << "Error: Memory Allocation Failed.";
exit(1);
}
else
{
cout << "New M Type added!" << endl << endl;
}
CurrentMCSize++;
}
Have I not properly initialized my pointer? Is my Add function actually lying to me and nothing is being added? I looked around but most answers I saw involved using a vector, which for the sake of this project I don’t think I’m allowed to use as the professor didn’t go over them.
You are asking the user to input the size of the collection during construction, but you never populate those elements of the collection. Then, when you call AddM, it continues from CurrentMCSize. You should instead initialize CurrentMCSize to zero in the constructor and not ask for it at all.
The problem occurs because this
for (int i = 0; i < CurrentMCSize; i++)
{
cout << i << ". " << Collection[i]->GetTitle();
}
starts at 0 but there is no guarantee that AddM() will begin adding at 0:
void MC::AddM()
{
int Selection;
if(CurrentMCSize < MCSize)
{
DisplayMTypeMenu();
Selection = GetMTypeSelection();
switch(Selection)
{
case 1: Collection[CurrentMCSize] = new AC;
Instead it will add at whatever CurrentMCSize is which could be fed into the constructor as something like 4. You have three separate values you want to track: max supported size, the size presently used and the next slot to allocate an item but you've collapsed the last two into one variable.
Related question - Any reason you don't want to simply use a std::vector and push_back?
Edit: Ah I didn't see it, Paddy beat me to it.
Related
I'm working on an assignment right now and when run my code returns this error:
main.cpp:60:20: error: ‘dataArr’ was not declared in this scope
if(tolower(dataArr[i].last) == tolower(lastName))
I'm not quite sure what I'm missing here. If I could at least get it to run I'd appreciate it. Thanks.
I thought arrays were declared globally so i thought it wouldn't be an issue in my functions
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
struct Database
{
string first;
string last;
string ID;
string phoneNum;
};
void lastSearch(string);
void idSearch(string);
int main()
{
Database dataArr[100];
ifstream myFile("library_database.txt");
int count = 0;
while(!myFile.eof() && count < 100)
{
myFile >> dataArr[count].first >> dataArr[count].last >> dataArr[count].ID >> dataArr[count].phoneNum;
cout << dataArr[count].first << " " << dataArr[count].last << " " << dataArr[count].ID << " " << dataArr[count].phoneNum << endl;
count++;
}
int input;
string search;
cout << "Would you like to search by last name or member ID?\n1. Last Name\n2. ID\n> ";
cin >> input;
while(input != 1 || input != 2)
{
cout << "Enter a valid answer.\n> ";
cin >> input;
}
if(input == 1)
{
cout << "Enter last name: ";
cin >> search;
lastSearch(search);
}
if(input == 2)
{
cout << "Enter ID: ";
cin >> search;
idSearch(search);
}
return 0;
}
void lastSearch(string lastName)
{
int num = 0;
for(int i = 0; i < 100; i++)
{
if(tolower(dataArr[i].last) == tolower(lastName))
{
cout << dataArr[i].first << " " << dataArr[i].last << " " << dataArr[i].ID << " " << dataArr[i].phoneNum << endl
num++;
}
}
if(num == 0)
{
cout << "No match was found in the file.";
}
}
voidSearch was removed to allow this to be posted
To answer the title of your post: because it isn't.
You declare dataArr in main, but you are trying to use it in lastSearch, so lastSearch can't see it. But you can pass it in as a parameter, that's probably the easiest fix:
void lastSearch(const string lastName, const Database *dataArr) { ... }
and call it like this:
lastSearch (search, dataArr);
Note the use of const (get into the habit of doing that whenever you can) and that your array 'decays' to a pointer when you pass it as a parameter like this, so don't be tempted to use sizeof in lastSearch. If you need to know the number of elements in the array, pass that as a parameter too.
Or, better, use std::array instead of a C-style array and then the size of the array is available in lastSearch without the need to pass it in separately. If you do that, you probably want to pass it by const reference to avoid copying it every time you call the function.
Finally, it might be time to learn about std::vector. At the expense of a little more complexity (but not much), this would avoid the need to allocate a fixed size array. Again, for the same reason, pass it around by reference.
Some bedtime reading: The Definitive C++ Book Guide and List
Arrays are not declared globally, they are declared where you declare them :-)
In your case, you declare it at the top of main() so that is its scope, from point of declaration to end of main(). Trying to use it in lastSearch() is therefore invalid.
The easiest fix is probably just to move the declaration immediately before main() so that it is global. But the easiest things is often not the right thing.
You would be better off embracing C++ fully(1) and using something like std::vector, whose size isn't arbitrarily limited to 100 (for example) and which you could pass around quite easily, something like:
#include <iostream>
#include <vector>
void function(const std::vector<int> &vec) {
std::cout << vec.size() << ' ' << vec[0] << '\n'; // Output: 2 42
}
int main() {
std::vector<int> x;
x.push_back(42);
x.push_back(99);
function(x);
}
The main advantages with vectors are that:
you're not limited to a maximum of 100 items;
you don't have to pass around the actual count of items read separately as with a raw array or even a std::array (you don't do that in your code but I assure you, that's a problem).
the size of the vector is an integral property of the vector, available anywhere the vector is in scope.
(1) There's a variety of developers I like to call C+ developers. These are the people that, though they claim to be C++ developers, have never really embraced the C++ way of doing things, sticking to C style programming practices like non-smart pointers or normal arrays :-)
Some of those things may still have a place in modern C++ code but you should be circumspect in their use.
Background:
I have created a player class and I want to ask the user how many players are going to play the game? Based on the user input I am trying to create that many instances of the player class. However, I used the following links to help me:
Create object using user input
http://www.cplusplus.com/forum/beginner/197342/
So, I tried their solution:
#include "Player.h"
int main() {
int totalPlayers = -1;
cout << "Enter total number of players: ";
while ((totalPlayers < 1) && (totalPlayers > 5)) {
cout << "How many players will be playing? (1-5): ";
cin >> totalPlayers;
}
vector<Player> players(totalPlayers);
system("pause");
}
I get the error: Unhandled exception at 0x763F40B2 in 16LinearChess.exe: Microsoft C++ exception: std::length_error at memory location 0x003BF690.
So, I googled this exact error and found this link: Error : std::length_error at memory location
So, firstly his code was no-where related to mine, but the error was same. I did not understand the answer, but I thought that I had to create the instances using heap memory. So I tried that:
#include "Player.h"
int main() {
int totalPlayers = -1;
cout << "Enter total number of players: ";
while ((totalPlayers < 1) && (totalPlayers > 5)) {
cout << "How many players will be playing? (1-5): ";
cin >> totalPlayers;
}
vector<Player> *players = new Player(totalPlayers);
delete[] players;
system("pause");
}
I got two errors: Severity Code Description Project File Line Suppression State
Error (active) E0144 a value of type "Player *" cannot be used to initialize an entity of type "std::vector<Player, std::allocator> *" 16LinearChess D:\Keshav\Programming Languages\C++\Beginner\01 Michael Dawson\16LinearChess\LinearChess.cpp 64
Severity Code Description Project File Line Suppression State
Error (active) E0289 no instance of constructor "Player::Player" matches the argument list 16LinearChess D:\Keshav\Programming Languages\C++\Beginner\01 Michael Dawson\16LinearChess\LinearChess.cpp
This is my Player class:
#include <iostream>
class Player : public Board {
protected:
int m_position;
Log logger;
int m_playerNumber;
public:
static int m_numberOfPlayers;
Player() :m_position(0) {
++m_numberOfPlayers;
m_playerNumber = m_numberOfPlayers;
}
void m_SetPlayerPosition(int &position) {
if ((position < 0) || (position > 100)) {
m_position = 0;
logger.Error("Position cannot be less than or greater than 100. Your position has been reset to 0 because you fell out of the map.");
}
else {
m_position = position;
}
m_SetBoardPosition(m_position, m_numberOfPlayers); // update the position on the board.
}
friend ostream &operator << (ostream &os, Player &player) {
os << "Player position on board: " << player.m_position << "\nPlayer Number: " << player.m_playerNumber << '\n';
return os;
}
};
int Player::m_numberOfPlayers = 0; // initializing total number of players.
Thank You!
The problem is with your while loop:
int totalPlayers = -1;
cout << "Enter total number of players: ";
while ((totalPlayers < 1) && (totalPlayers > 5)) {
cout << "How many players will be playing? (1-5): ";
cin >> totalPlayers;
}
The while loop will only run if the condition is true, but the condition can never be true since no number can be smaller than 1, but also greater than 5. And since the condition is not true, the while loop will never run, and totalPlayers will be equal to -1, which is something you never want if you're trying to access an array index.
Change it to this: totalPlayers < 1 || totalPlayers > 5 with an || instead, and you should be fine.
And for the error:
Unhandled exception at 0x763F40B2 in 16LinearChess.exe: Microsoft C++ exception: std::length_error at memory location 0x003BF690.
Your code threw an exception because totalPlayers is equal to -1. So you basically did this:
vector<Player> players(-1);
Which makes no sense since you are creating an array that hold -1 elements? So the code threw an exception telling you that something is wrong. The std::length_error should give a hint about what's wrong.
Also like many of the comments have stated, don't do this:
vector<Player> *players = new Player(totalPlayers);
The whole purpose of a vector is so you don't do that. Your first example works fine:
vector<Player> players(totalPlayers);
std::length_error occurs if std::vector attempts to resize to a size that is above the max_size(). Most often, this happens from a bad input -- such as -1 which will be converted to the largest unsigned value for std::vector<T>::size_type.
Judging by the code you shared, the problem is actually due to your while loop condition:
while ((totalPlayers < 1) && (totalPlayers > 5))
It is not possible for totalPlayers to be both simultaneously less than 1 and greater than 5 -- so this loop is never entered. Since the default value you assign to totalPlayers is -1, the size you resize to overflows and becomes the largest unsigned value -- which triggers the std::length_error.
Fixing this condition should fix your error.
I've been working on a Shape program lately ( Some of you might remember my other questions about this... ;/ ) And I have a tiny problem which I want to fix.
In my Menu class, which holds all the functions related to the menu. I have a unique_ptr vector with the type of my base class Shape which holds all of the newly created objects ( Circles, Rectangles, ect )
protected:
vector<unique_ptr<Shape>> _shapes;
One of the functions that I want to create is supposed to change the values of the variables in a given shape based on it's index. To do so, I was planning to print the vector to the user, and then let him to choose the index of the shape that he wants to change.
void Menu::printShapes() const
{
int i = 0;
for (auto p = _shapes.begin(); p != _shapes.end(); p++, i++)
{
cout << i + " ";
(*p)->printDetails();
cout << endl;
}
}
The problems lays in my main program which is going to use my Menu functions. Because I don't want the user to be able to enter values which are outside of my vector, I have to check if the given input is between 0 and the size of the vector. But I cannot access this info from my main function without making the vector public or make a return statement from the printShapes() function, which will make the code messy and not intuitive as I want it to be.
So my question is: Is there a way to find the size of the vector at the Menu function from the main function without making the changes I stated above? Because in the end I want to be able to just do menu.printShapes() and then let the user to choose the index of the shape that he wants to change
this is my main function as of now:
Menu menu;
int input = 0, wait = 0;
while (input != 4)
{
cout << "1: Add New Shape: " << endl;
cout << "2: Modify Existing Shape: " << endl;
cout << "3: Delete All Shapes: " << endl;
cout << "4: Exit: " << endl;
while (input < MIN || input > MAX)
{
cin >> input;
cin.ignore(numeric_limits<streamsize>::max(), '\n');
std::cin >> wait;
}
switch (input)
{
case 1:
{
cout << "1: Circle: " << endl;
cout << "2: Rectangle: " << endl;
cout << "3: Triangle: " << endl;
cout << "4: Arrow: " << endl;
while (input < MIN || input > MAX)
{
cin >> input;
cin.ignore(numeric_limits<streamsize>::max(), '\n');
std::cin >> wait;
}
menu.createShape(input);
}
case 2:
{
/*
I want to be able to access the size of the vector from here
So I could do something like that:
menu.printShapes();
while (input < 0 || input > vectorSize)
{
:Get the index of the shape that the user wants to modify
}
Instant of doing
size = menu.printShapes();
*/
}
}
}
You're way overthinking this.
You just need to add a public function that returns the current size of the vector:
// Declaration in your class
size_t numberOfShapes() const;
// Definition
size_t Menu::numberOfShapes() const
{
return _shapes.size();
}
. Then, when you want to know the size, call that function.
menu.printShapes();
while (input < 0 || input > menu.numberOfShapes())
{
// Get the index of the shape that the user wants to modify
}
Simple!
By the way, I think you meant >= there, not >.
You have at least a few options; depending on the details of the modify-existing-shape operation.
The easiest thing would probably be to have your Menu type expose a method to tell you how many shapes it's managing. I agree you shouldn't make the vector public because the program doesn't need to know it's a vector specially, but if "knowing how many existing shapes the menu is managing" is a requirement (which it seems to be) then exposing it seems reasonable.
Alternatively, depending on the return type of the modify operation you could return an optional or a variant. If you have 7 shapes and I ask you to modify the 6th then you might tell me that it worked or maybe the new dimensions, but if I ask you to modify the 9th you might tell me it's an invalid index.
The difference becomes whether to obligate the caller to be informed and ask a valid question, or whether you want to be more robust and answer and handle a broader domain of questions. I don't think it makes a big difference in this case but I tend toward the second kind of solution simply because it means any potential caller is protected from going out of range instead of all of then having to check the count then do their own validation.
For my homework assignment I'm supposed to make a create-your-own-adventure story. There are certain words in the text that are in all caps to represent boolean values that I need to display at the end if the player got them, like a status effect or something. I'm having trouble figuring out how to pass the booleans to the functions so that it makes it to the end of the program where I can display it. My program has functions within functions.
I've tried making the function that sets the boolean to true a boolean itself, then returning the boolean but that just ends the program it seems. I've also tried passing it through the first function call to see if it reaches the second but it doesn't seem like it wants to.
void A1();
bool A100(bool INTIM);
void A167();
void A232();
void A290();
void A13();
void A212();
void A173();
void A159();
void A161();
int main() {
bool INTIM;
A1();
cout << INTIM << endl;
return 0;
}
void A1()
{
int choice;
cout << "Well, Mr Artanon, ...\n 1. ’It’s you who’ll get a rare cut
across that corpulent neck of yours if you don’t speed things along, you
feckless blob of festering lard.’\n 2. ’Surely in such an industrious
kitchen, there must be a starter or two ready to send along and sate His
Abhorentness’s appetite?’\n (enter a menu option): ";
cin >> choice;
while (choice != 1 && choice != 2)
{
cout << "Enter in a valid choice (1 or 2)";
cin >> choice;
}
if (choice == 1)
{
A100();
}
if (choice == 2)
{
A167();
}
}
bool A100(bool INTIM)
{
int choice;
INTIM = true;
cout << " Repugnis turns a paler...\n 1. Onwards, Mr Artanon.\n (enter
in a menu option): ";
cin >> choice;
while (choice != 1)
{
cout << "Enter in a valid option (1)";
}
return INTIM;
A232();
}
What I'm wanting to happen is, the bool INTIM to be passed along so i can display it back in main with the cout statement. I know it will just be a 1 or 0 at the end but I'm just trying to get it to show up at least in the end when I display it. Again there are functions within functions in this program and that might be my problem but I wouldn't think so. There is also functions that come after this, this is not the end of the program and if I need to post the whole thing I will
Calling A100 as written, you need to pass in INTIM and accept the return value
INTIM = A100(INTIM);
But... The initiqal state of INTIM is never used, so you could
INTIM = A100();
and change A100 to look more like
bool A100()
{
int choice;
cout << " Repugnis turns a paler...\n 1. Onwards, Mr Artanon.\n (enter in a menu option): ";
cin >> choice;
while (choice != 1)
{
cout << "Enter in a valid option (1)";
cin >> choice; // added here because otherwise choice never changes
// and this loop will go on for a long, long time.
}
A232(); // moved ahead of return. Code after a return is not run
return true;
}
But since A232 is called and may set additional flags you cannot return, you have a design flaw: What if A232 also modifies a boolean? You can only return one thing from a function. You could pass A232's boolean in by reference, but what it A232 then calls B484 and it also has a boolean?
You don't want to have to pass around every possible boolean, that would be a confusing mess, so consider making a data structure that stores all of your booleans to pass around.
And that leads to an even better idea: encapsulating the booleans and the functions in the same data structure so that you don't have to pass anything around; it's all in the same place.
Do I need to pass them [the boolean results] to the functions?
Often, but not always, it is my preference to pass them by reference, and yes, it can get to be a big chain thru many functions. sigh.
But your question is "Do you need to pass them ...".
The answer is No.
Because
a) you have tagged this post as C++, and
b) the key feature of C++ is the user-defined-class.
Consider declaring every 'adventurous function' of your story within a class scope.
Each 'adventurous function', as an attribute of the class, is implemented with one 'hidden' parameter, the 'this' pointer to the class instance.
So .. if you place all your 'result' booleans as data attributes of the class, invoking any 'adventurous function' will also 'pass' all the class instance data attributes (all your bools!) as part of the invocation. No data is actually moving, just a pointer, the 'this' pointer.
It might look something like this:
#include <iostream>
using std::cout, std::cerr, std::flush, std::endl;
// using std::cin;
#include <iomanip>
using std::setw, std::setfill;
#include <sstream>
using std::stringstream;
#include <string>
using std::string;
namespace AS // Adventure Story
{
class CreateYourOwnAdventureStory_t
{
private:
// diagnostic purposes
stringstream ssUI;
// command line arguments concatenated into one string
// contents: strings convertable to ints to mimic cin
bool INTIM;
// other results go here
public:
int operator()(int argc, char* argv[]) {return exec(argc, argv);}
private:
int exec(int argc, char* argv[])
{
int retVal = 0;
// capture all command line arguments into a string
for (int i=1; i<argc; ++i)
ssUI << argv[i] << " ";
cout << "\n ssUI: " << ssUI.str() << "\n\n\n";
A1();
cout << "\n INTIM : " << INTIM << endl;
// ?more here?
return retVal;
}
void A1()
{
int choice = 0;
cout << "Well, Mr Artanon, ...\n "
"\n 1. ’It’s you who’ll get a rare cut across that corpulent neck of yours "
"if you don’t speed things along, you feckless blob of festering lard. "
"\n 2. ’Surely in such an industrious kitchen, there must be a starter or two "
"ready to send along and sate His Abhorentness’s appetite?’"
"\n (enter a menu option): ";
ssUI >> choice; // cin >> choice;
if (choice == 1) { A100(); }
if (choice == 2) { A167(); }
}
void A100()
{
int choice = 0;
INTIM = true;
ssUI >> choice; // cin >> choice;
cout << "\n\n A100() choice:" << choice
<< " INTIM: " << INTIM << endl;
}
void A167()
{
int choice = 0;
INTIM = false;
ssUI >> choice; // cin >> choice;
cout << "\n\n A167() choice:" << choice
<< " INTIM: " << INTIM << endl;
}
// other action-functions go here
}; // class CreateYourOwnAdventureStory_t
typedef CreateYourOwnAdventureStory_t CreateYOAS_t;
} // namespace AS
int main(int argc, char* argv[]){return AS::CreateYOAS_t()(argc,argv);}
Notes:
This example grabs the command line parameters and appends them to a string stream. The result is use-able in a fashion much like your cin statements.
Did you notice you (probably) will not need forward declarations for your functions? The compiler has to scan a lot of the class declaration to decide various issues, and thus can figure out that A100 (and A167) are actually with-in the scope of AS::CreateYOAS_t::. The functions can still be moved into a cpp file, so you can still take advantage of separate compilation. (and maybe save some effort compiling smaller files, and only the changed files.)
Did you notice that the functions accessing INTIM simply use the bool, without needing any 'this->' to de-reference?
Main invokes a simple Functor. Nothing else. Main invokes operator(). Simple, minimal. The ctor and dtor are currently default. If you need to use the ctor to initialize results or other intermediate info, I would simply add it near the operator() implementation.
PS: You mentioned using bools to return results. You might as, an alternative, consider using a stringstream ... a single stream with text ... use like a log for capturing the ongoing game, or for a single simple overall report to the user.
Good luck.
I'm having trouble figuring out how to properly create an object depending on the user's choice.
In the program, I ask the user which they class they want to be--Knight or Wizard. I take input '1' or '2' to represent Knight and Wizard.
I made a switch statement, and within case 1, I declared an object Knight, and the same for Wizard.
I need to use these objects outside of the switch statement, but I can't. I tried to make a 'default' object by making 'Player player;' but because the Player class has a pure virtual function, I can't do that either.
How do I do this effectively?
This is what I have so far:
int main()
{
std::string plyrName;
int input;
bool foo = false;
std::cout << "What is your name?\n";
std::cin >> plyrName;
std::cin.ignore(1000, '\n');
std::cout << "\nWelcome, " << plyrName << ". What class would you like to be?\n";
std::cout << "1. Knight.\n2. Wizard.\n";
std::cin >> input;
while (input != 1 && input != 2)
{
if (foo == true)
std::cout << "Please enter 1 for Knight and 2 for Wizard.\n";
if (!(std::cin >> input))
{
std::cin.clear();
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
std::cout << "\n";
std::cout << "Only integers are allowed.\n";
}
else
std::cout << "\n";
foo = true;
}
switch (input)
{
case 1:
{
Wizard player;
break;
}
case 2:
{
Knight player;
break;
}
}
std::cout << "\nHere is your player information summary.\n";
std::cout << player.classType();
system("pause");
return 0;
}
I need to access the player object after is has been created, because I want to output to the user which class they selected. Both Knight and Wizard classes have a function to output this.
EDIT: I have a follow up question. In the diagram, Knight & Wizard have a static variable 'special attack name'. How can I access this variable in the main function? The solution of using unique_ptr means that the pointer will point to the base class Player, thus not allowing access to the derived class members such as the static variable 'special attack name'. Do I have a flaw in my design?
In your case, because you want to accomplish polymorphism, you should go for pointers and references. Why? I would highly recommend this beautiful answer. Why doesn't polymorphism work without pointers/references?
So, should you go for a raw pointer, something like Player *?
In almost all scenarios, you should never ever go for raw pointers and especially, when it points to dynamic memory. Simply because any programming error or an exception might lead to delete getting skipped.
Therefore, I would highly recommend you to go for smart pointers introduced in C++11 like unique_ptr and shared_ptr which follow RAII pattern and guarantee deinitialization.
Here is an example of usage of unique_ptr in your case.
#include <memory>
using PlayerPtr = std::unique_ptr<Player>;
using KnightPtr = std::unique_ptr<Knight>;
using WizardPtr = std::unique_ptr<Wizard>;
int main()
{
...
PlayerPtr playerPtr = nullptr;
switch (input) {
case 1: {
playerPtr = KnightPtr(new Knight);
}
break;
case 2: {
playerPtr = WizardPtr(new Wizard);
}
break;
}
// use playerPtr outside.
}
Edit:
As rightly pointed out by HTNW, you must go for std::make_unique instead of using new. But remember, that is a C++14 concept. You must have compiler support for it.
if you create your variable inside the switch case scope it will get deleted as soon as you leave that scope leading you to UB so you declare it as a pointer so it can outlive the conditional statement ie : you declare it as the base class pointer before & you give it to where it points inside conditional statement
#include<memory>
int main()
{
std::string plyrName;
int input;
bool foo = false;
//create your player ptr
std::unique_ptr<Game_Object> player;
std::cout << "What is your name?\n";
std::cin >> plyrName;
std::cin.ignore(1000, '\n');
std::cout << "\nWelcome, " << plyrName << ". What class would you like to be?\n";
std::cout << "1. Knight.\n2. Wizard.\n";
std::cin >> input;
while (input != 1 && input != 2)
{
if (foo == true)
std::cout << "Please enter 1 for Knight and 2 for Wizard.\n";
if (!(std::cin >> input))
{
std::cin.clear();
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
std::cout << "\n";
std::cout << "Only integers are allowed.\n";
}
else
std::cout << "\n";
foo = true;
}
switch (input)
{
case 1:
{ // initialize it and it would work perfectly as you intend
player = std::make_unique<WIZARD>();
break;
}
case 2:
{ //****
player = std::make_unique<KNIGHT>();
break;
}
}
std::cout << "\nHere is your player information summary.\n";
std::cout << player->classType();
system("pause");
return 0;
}
Someone correct me if I'm wrong, but objects are only valid within the scope they are created so once you are out of that switch statement those objects are not accessible anymore.
You should declare a GAME OBJECT class object outside the switch statement and then create either the wizard or the knight (as both classes inherit GAME OBJECT).