My object was not declared in this scope, even after assigning it inside a switch statement

Hello, I am making a class for a character with some attributes. I also made an inherited class. I made a system for choosing between different objects made from the first class and then storing the chosen one in the inherited class as an object(using a key system"getch()" (nevermind it pls)). The syntax worked but the chosen object isnt being declared in my cout command. look at the code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
#include <iostream>
#include <conio.h>
#include <string>
#include <windows.h>

#define K1 49
#define K2 50
#define K3 51

class Character {
public:
    string type;
    string name;
    float HP;
    float MP;
    float str;
    float def;
    float agility;
    int LVL;

    Character(string atype, string aname, float aHP, float aMP, float astr, float adef, float aagility, int aLVL){
        type = atype;
        name = aname;
        HP = aHP;
        MP = aMP;
        str = astr;
        def = adef;
        agility = aagility;
        LVL = aLVL;
    }
};

class Chosen: public Character{
public:
    using Character::Character;
};

int getch();

int main()
{

    Character war("Warrior", "Achilles",    100, 30,  50,  35,    30,     1);
    Character nin("Assassin", "Jin Sakai",  80,  50,  50,  30,    50,     1);
    Character mag("Wizard", "Merlin",       60,  100, 40,  25,    20,     1);

cout << "\n\n\tPress 1 for warrior \tPress 2 for Assassin \tPress 3 for wizard\n";

    string chosenChar;

    switch(getch()){
        case K1:
            {
                chosenChar = war.type;
                cout << "\n\t\t\tYou have chosen the " << chosenChar << endl;
                Chosen chosenOne("Warrior", "Achilles",    100, 30,  50,  35,    30,     1);
                break;
            }


        case K2:
            {
                chosenChar = nin.type;
                cout << "\n\t\t\tYou have chosen the " << chosenChar << endl;
                Chosen chosenOne("Assassin", "Jin Sakai",  80,  50,  50,  30,    50,     1);
                break;
            }


        case K3:
            {
                chosenChar = mag.type;
                cout << "\n\t\t\tYou have chosen the " << chosenChar << endl;
                Chosen chosenOne("Wizard", "Merlin",       60,  100, 40,  25,    20,     1);
                break;
            }

    }

    cout << chosenOne.HP << endl;

    return 0;
}

sorry for the mess. The error is
 
|80|error: 'chosenOne' was not declared in this scope


chosenOne is local to the enclosing block with the case statements and can't be accessed outside.

One possible way round this is which compiles OK:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
#include <iostream>
#include <conio.h>
#include <string>
using namespace std;

#define K1 49
#define K2 50
#define K3 51

class Character {
public:
	string type;
	string name;
	float HP;
	float MP;
	float str;
	float def;
	float agility;
	int LVL;

	Character() {}

	Character(string atype, string aname, float aHP, float aMP, float astr, float adef, float aagility, int aLVL) {
		type = atype;
		name = aname;
		HP = aHP;
		MP = aMP;
		str = astr;
		def = adef;
		agility = aagility;
		LVL = aLVL;
	}
};

class Chosen : public Character {
public:
	using Character::Character;
	Chosen() {}
};

int main() {

	Character war("Warrior", "Achilles", 100, 30, 50, 35, 30, 1);
	Character nin("Assassin", "Jin Sakai", 80, 50, 50, 30, 50, 1);
	Character mag("Wizard", "Merlin", 60, 100, 40, 25, 20, 1);

	cout << "\n\n\tPress 1 for warrior \tPress 2 for Assassin \tPress 3 for wizard\n";

	string chosenChar;
	Chosen* chosenOne {};

	switch (_getch()) {
		case K1:
				chosenChar = war.type;
				cout << "\n\t\t\tYou have chosen the " << chosenChar << endl;
				chosenOne = new Chosen("Warrior", "Achilles", 100, 30, 50, 35, 30, 1);
				break;

		case K2:
				chosenChar = nin.type;
				cout << "\n\t\t\tYou have chosen the " << chosenChar << endl;
				chosenOne = new Chosen("Assassin", "Jin Sakai", 80, 50, 50, 30, 50, 1);
				break;

		case K3:
				chosenChar = mag.type;
				cout << "\n\t\t\tYou have chosen the " << chosenChar << endl;
				chosenOne = new Chosen("Wizard", "Merlin", 60, 100, 40, 25, 20, 1);
				break;
	}

	cout << chosenOne->HP << endl;

	delete chosenOne;
}

Perfect!
Thank you so much man!
As seeplus said your chosen character is local to the enclosing block. You could create an "empty character" which is a clone of the chosen one, copied in the case statement, but out of the block. This way you have an (false) access to the features. It's not an efficient alternative, but it works ++

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
#include <iostream>
#include <conio.h>
#include <string>
#include <windows.h>

#define K1 49
#define K2 50
#define K3 51

using namespace std;

class Character {
public:
    string type;
    string name;
    float HP;
    float MP;
    float str;
    float def;
    float agility;
    int LVL;

    Character(string atype, string aname, float aHP, float aMP, float astr, float adef, float aagility, int aLVL) {
        type = atype;
        name = aname;
        HP = aHP;
        MP = aMP;
        str = astr;
        def = adef;
        agility = aagility;
        LVL = aLVL;
    }
};

class Chosen : public Character {
public:
    using Character::Character;
};

int main()
{  // an empty charactere
    Character who("Class", "Name", 0, 0, 0, 0, 0, 0);

    Character war("Warrior", "Achilles", 100, 30, 50, 35, 30, 1);
    Character nin("Assassin", "Jin Sakai", 80, 50, 50, 30, 50, 1);
    Character mag("Wizard", "Merlin", 60, 100, 40, 25, 20, 1);

    cout << "Press 1 for warrior\tPress 2 for Assassin\tPress 3 for wizard\n";
    string chosenChar;

    switch (_getch()) 
    {
        case K1:
        {
            chosenChar = war.type;
            cout << "You have chosen the " << chosenChar << endl;
            Chosen chosenOne("Warrior", "Achilles", 100, 30, 50, 35, 30, 1);
            who = chosenOne; // clone the chosen one
            break;
        }

        case K2:
        {
            chosenChar = nin.type;
            cout << "You have chosen the " << chosenChar << endl;
            Chosen chosenOne("Assassin", "Jin Sakai", 80, 50, 50, 30, 50, 1);
            who = chosenOne; // clone the chosen one
            break;
        }

        case K3:
        {
            chosenChar = mag.type;
            cout << "You have chosen the " << chosenChar << endl;
            Chosen chosenOne("Wizard", "Merlin", 60, 100, 40, 25, 20, 1);
            who = chosenOne; // clone the chosen one
            break;
        }
    }

    cout << "Some player features : " << endl
         << who.type << endl 
         << who.name << endl 
         << who.HP << endl;

    return 0;
}

Modified to fit with Visual Studio.
Last edited on
Thank you very much too!
yours works very well.
Doing it that way, then:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
#include <iostream>
#include <conio.h>
#include <string>
//#include <windows.h>

#define K1 49
#define K2 50
#define K3 51

using namespace std;

class Character {
public:
	string type;
	string name;
	float HP {};
	float MP {};
	float str {};
	float def {};
	float agility {};
	int LVL {};

	Character() {}

	Character(string atype, string aname, float aHP, float aMP, float astr, float adef, float aagility, int aLVL) {
		type = atype;
		name = aname;
		HP = aHP;
		MP = aMP;
		str = astr;
		def = adef;
		agility = aagility;
		LVL = aLVL;
	}
};

class Chosen : public Character {
public:
	using Character::Character;
};

int main() {  // an empty charactere
	Character who;

	const Character war("Warrior", "Achilles", 100, 30, 50, 35, 30, 1);
	const Character nin("Assassin", "Jin Sakai", 80, 50, 50, 30, 50, 1);
	const Character mag("Wizard", "Merlin", 60, 100, 40, 25, 20, 1);

	cout << "Press 1 for warrior\tPress 2 for Assassin\tPress 3 for wizard\n";
	string chosenChar;

	switch (_getch()) {
		case K1:
				who = war;
				break;

		case K2:
				who = nin;
				break;

		case K3:
				who = mag;
				break;
	}

	chosenChar = who.type;
	cout << "You have chosen the " << chosenChar << '\n';

	cout << "Some player features : " << '\n'
		<< who.type << '\n'
		<< who.name << '\n'
		<< who.HP << '\n';
}

Last edited on
Or to avoid an unnecessary assignment (and 'fixing' the constructor), then:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
#include <iostream>
#include <conio.h>
#include <string>
//#include <windows.h>

#define K1 49
#define K2 50
#define K3 51

using namespace std;

class Character {
public:
	string type;
	string name;
	float HP {};
	float MP {};
	float str {};
	float def {};
	float agility {};
	int LVL {};

	Character() {}

	Character(const string& atype, const string& aname, float aHP, float aMP, float astr, float adef, float aagility, int aLVL) :
		type(atype), name(aname), HP(aHP), MP(aMP), str(astr), def(adef), agility(aagility), LVL(aLVL) {}
};

class Chosen : public Character {
public:
	using Character::Character;
};

int main() {  // an empty charactere
	const Character war("Warrior", "Achilles", 100, 30, 50, 35, 30, 1);
	const Character nin("Assassin", "Jin Sakai", 80, 50, 50, 30, 50, 1);
	const Character mag("Wizard", "Merlin", 60, 100, 40, 25, 20, 1);

	cout << "Press 1 for warrior\tPress 2 for Assassin\tPress 3 for wizard\n";
	string chosenChar;

	Character who { [&] {
	switch (_getch()) {
		case K1:
				return war;

		case K2:
				return nin;

		case K3:
				return mag;
	} }() };

	chosenChar = who.type;
	cout << "You have chosen the " << chosenChar << '\n';

	cout << "Some player features : " << '\n'
		<< who.type << '\n'
		<< who.name << '\n'
		<< who.HP << '\n';
}

Last edited on
thank you again for replying.
I have a question though...
What did you do here???

1
2
3
Character who { [&] {
switch (_getch()) {
} }() };

I don't understand the syntax.
mind that I am a beginner.
The [] syntax is for a lambda.

For more info, see:
https://www.learncpp.com/cpp-tutorial/introduction-to-lambdas-anonymous-functions/

For an e-book on lambdas, see:
https://leanpub.com/cpplambda

Note the book bundles available - 3 e-books for $30
https://leanpub.com/bookstore?type=all&search=c%2B%2B%20lambda
Last edited on
This is less contrived and may be easier to understand.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
#include <iostream>
#include <string>

struct Character
{
    std::string type;
    std::string name;
    double HP = 0 ;
    double MP = 0 ;
    double str = 0 ;
    double def = 0 ;
    double agility = 0 ;
    int LVL = 0 ;

    friend std::ostream& operator << ( std::ostream& stm, const Character& ch )
    { return stm << "Character{ " << ch.name << " (" << ch.type << ", HP:" << ch.HP << ") }" ; }
};

int main()
{
    // create the three prototypical characters
    const Character war { "Warrior", "Achilles", 100, 30, 50, 35, 30, 1 } ;
    const Character nin { "Assassin", "Jin Sakai", 80, 50, 50, 30, 50, 1 };
    const Character mag { "Wizard", "Merlin", 60, 100, 40, 25, 20, 1 };

    const Character* prototype = nullptr ; // pointer to a prototypical character

    while( prototype == nullptr ) // repeat till the user chooses a valid character
    {
        std::cout << "choose character (1 warrior / 2 assassin / 3 wizard): ";
        char ch = '1' ;
        std::cin >> ch ;

        switch( ch )
        {
            case '1' : prototype = std::addressof(war) ; break ;
            case '2' : prototype = std::addressof(nin) ; break ;
            case '3' : prototype = std::addressof(mag) ; break ;
            default : std::cout << "invalid input; try again. enter 1, 2 or 3\n" ;
        }
    }

    Character chosen_character = *prototype ; // chosen character is a copy of the prototypical character
    std::cout << "you have chosen " << chosen_character << '\n' ;
}
This has potentially 2 issues. a) prototype is a pointer to const so the attributes of the character can't be changed. b) if made non-const (and war, nin, mag etc) then you can only have 1 instance of war/nin/mag as any changes effect the one object.

Whether these are actual issues depends, of course, on how the game is coded. But that's why in my original code I used a pointer with new.

Hence consider - which also uses type Chosen for the chosen character and a smart pointer (avoiding delete):


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
#include <iostream>
#include <conio.h>
#include <string>
#include <memory>
//#include <windows.h>

#define K1 49
#define K2 50
#define K3 51

class Character {
public:
	std::string type;
	std::string name;
	float HP {};
	float MP {};
	float str {};
	float def {};
	float agility {};
	int LVL {};

	Character() {}

	Character(const std::string& atype, const std::string& aname, float aHP, float aMP, float astr, float adef, float aagility, int aLVL) :
		type(atype), name(aname), HP(aHP), MP(aMP), str(astr), def(adef), agility(aagility), LVL(aLVL) {}

};

class Chosen : public Character {
public:
	using Character::Character;

	Chosen(const Character& ch) : Character(ch) {}

	friend std::ostream& operator << (std::ostream& stm, const Chosen& ch) {
		return stm << "Character{ " << ch.name << " (" << ch.type << ", HP:" << ch.HP << ") }";
	}
};

const Character war("Warrior", "Achilles", 100, 30, 50, 35, 30, 1);
const Character nin("Assassin", "Jin Sakai", 80, 50, 50, 30, 50, 1);
const Character mag("Wizard", "Merlin", 60, 100, 40, 25, 20, 1);

int main() {
	std::unique_ptr<Chosen> who {};

	std::cout << "Press 1 for warrior\tPress 2 for Assassin\tPress 3 for wizard: ";

	while (!who) {
		switch (_getche()) {
			case K1:
				who.reset(new Chosen {war});
				break;

			case K2:
				who.reset(new Chosen { nin });
				break;

			case K3:
				who.reset(new Chosen { mag });
				break;

			default:
				std::cout << "\nInvalid input: Try again. Enter 1, 2 or 3: ";
				break;
		}
	}

	std::cout << '\n' << *who << '\n';
}


Last edited on
> a) prototype is a pointer to const so the attributes of the character can't be changed.

Attributes of the prototype can't be changed; and it should not be changed.
Attributes of chosen_character can be changed; it is just a copy of a prototype.

Just in case someone might not understand this, I had added a comment clarifying that it is a copy.
1
2
// Line 43
Character chosen_character = *prototype ; // chosen character is a copy of the prototypical character 



> b) if made non-const

There is no good reason to make the prototypes non-const. That the prototypes are const does not imply that all their copies must also be const.


> But that's why in my original code I used a pointer with new.

Which too (dynamic allocation, new) is totally unnecessary in this code. Using a pointer does not necessarily force you to use dynamic allocation.

CoreGuidelines: R.5: Prefer scoped objects, don’t heap-allocate unnecessarily
https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#Rr-scoped

:) :) Ok. I didn't pay sufficient attention to L43. It was at the bottom of my display...

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
#include <iostream>
#include <conio.h>
#include <string>
//#include <windows.h>

#define K1 49
#define K2 50
#define K3 51

class Character {
public:
	std::string type;
	std::string name;
	float HP {};
	float MP {};
	float str {};
	float def {};
	float agility {};
	int LVL {};

	Character() {}

	Character(const std::string& atype, const std::string& aname, float aHP, float aMP, float astr, float adef, float aagility, int aLVL) :
		type(atype), name(aname), HP(aHP), MP(aMP), str(astr), def(adef), agility(aagility), LVL(aLVL) {}

};

class Chosen : public Character {
public:
	using Character::Character;

	Chosen(const Character& ch) : Character(ch) {}

	friend std::ostream& operator << (std::ostream& stm, const Chosen& ch) {
		return stm << "Character{ " << ch.name << " (" << ch.type << ", HP:" << ch.HP << ") }";
	}
};

const Character war("Warrior", "Achilles", 100, 30, 50, 35, 30, 1);
const Character nin("Assassin", "Jin Sakai", 80, 50, 50, 30, 50, 1);
const Character mag("Wizard", "Merlin", 60, 100, 40, 25, 20, 1);

int main() {
	std::cout << "Press 1 for warrior\tPress 2 for Assassin\tPress 3 for wizard: ";

	const Character* prototype {};

	while (!prototype) {
		switch (_getche()) {
			case K1:
				prototype = std::addressof(war);
				break;

			case K2:
				prototype = std::addressof(nin);
				break;

			case K3:
				prototype = std::addressof(mag);
				break;

			default:
				std::cout << "\nInvalid input: Try again. Enter 1, 2 or 3: ";
				break;
		}
	}

	Chosen who { *prototype };

	std::cout << '\n' << who << '\n';
}

Last edited on
Topic archived. No new replies allowed.