Help bypassing a "not declared in this scope" error

I am pretty sure I understand the issue here, but I am not sure how to get past it.

I am attempting to use a user select a profession which will generate a certain child class as a particular object name.
So I have:
1
2
3
4
5
6
 	if (menu == 1)   {
		ranger combatant1;
	}
	else if (menu == 2)   {
		warrior combatant1;
	}

and after the selection attempt to access the combatant1 object and get a "not declared in this scope" error in the compiler. So, I am pretty certain that the compiler cant track where the object was declared because it is nested in an 'if' statement, but I am not sure how to properly create an object that might be one of a number of different possible children in a way the compiler will like.
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
#include "The_Awesome_Combatant_Types.h"

#include <memory>

int main(){
//Let ranger and warrior be children of a common parent combatant_type
    std::shared_ptr<combatant_type> combatant1(nullptr);

    int menu(0);
//Modify menu...

   switch(menu){
      case 1:
         combatant1.reset(new ranger());
         break;
      case 2:
         combatant1.reset(new warrior());
         break;
//Blah blah blah...
   }

//Blah blah blah...
   combatant1->do_something(); //Virtual function from combatant_type that
                                                 // is overridden in ranger and/or warrior
//Blah blah blah...

   return 0;
}


Yay for polymorphism.

Edit:
Links!
http://en.wikipedia.org/wiki/Polymorphism_(computer_science)
http://www.cplusplus.com/doc/tutorial/polymorphism/

And an example I suppose:
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
#include <iostream>
#include <memory>

using namespace std;

struct Parent{
    virtual void funky() = 0;
    virtual ~Parent(){}
};

struct Child1 : Parent{
    void funky(){cout << "Child 1";}
};

struct Child2 : Parent{
    void funky(){cout << "Child 2";}
};

int main()
{
    shared_ptr<Parent> ptr(new Child1());
    ptr->funky();
    cout << '\n';
    ptr.reset(new Child2());
    ptr->funky();
    cout << '\n';

    return 0;
}
Child 1
Child 2

http://ideone.com/7H9U7y
Last edited on
It is not that the compiler can't "track" it, the object no longer exists.
You've got two choices:
- declare the object before the if block (check out: inheritance, polymorphism, strategy pattern)
- don't refer to the object after the if block
Thanks Guys.

Daleth, hilariously, polymorphism is next week in the class that I am doing this for. I was trying to reason out my code and a basic logic tree was the only thing I was coming up with... I knew there was something better, just didn't explore it yet. Your info should give me a leg up for next week. I am now trying to figure out why I am seeing that 'nullptr' was not declared in this scope, but that seems more like I am missing a tidbit than going at it the wrong way.

ne555, good stuff to remember... I wasn't really sure how to state it, but I knew the issue was coming from that block. It looks far too ugly to be good code.
The 'nullptr' not declared is probably because you aren't using a C++11 compiler, or if you are you haven't turned on support for it.
NT3, I am using a C++ 11 compiler so I suspect it is a issue with turning on support for nullptr as you say. However I do not seem to be having much luck finding where nullptr lives to turn it on.
Alright then... silly me. My problem with nullptr seems to have been that I did not need it as there is nothing to pass in when creating combatant1 (unless I am completely misunderstanding what is happening there (which is entirely possible)).

That unfortunately leaves me at
assignment3.cpp:245: error: request for member ‘reset’ in ‘combatant1’, 
which is of non-class type ‘std::shared_ptr<combatant>()’
from the following.

1
2
3
4
5
6
7
8
std::shared_ptr<combatant> combatant1;	
	
	if (menu == 1)   {
		combatant1.reset(new warrior);
	}
	else if (menu == 2)   {
		combatant1.reset(new ranger);
	}

Last edited on
> request for member ‘reset’ in ‘combatant2’
your code does not have any `combatant2'

Oh sorry, I have two bits of code, with the same error and the only difference is the 'combatant1' and 'combatant2' as I am trying to do the same thing on two different objects. It seems to me like doubling the code and errors in a post is redundant and less than useful.

Edited above to clarity.
Last edited on
What specific compiler are you using? Have you included <memory>? That code compiles perfectly fine for me: http://coliru.stacked-crooked.com/a/9f47000380e4ac1c
Using g++ on a linux server. Though I am not sure how to get any specific version details out of it, I am told we have C++11.

I do have <memory> included as well.
To get the version of the compiler, use g++ -v and it should give you some information. The most recent stable version is 4.8.2 (maybe 4.9 by now). Try just compiling, for example, the code in the link I posted to see if it is to do with the compiler or due to something else in your code that we might have missed.
Well here is my version info, looks a little older:

Target: x86_64-redhat-linux
Configured with: ../configure --prefix=/usr --mandir=/usr/share/man --infodir=/usr/share/info --with-bugurl=http://bugzilla.redhat.com/bugzilla --enable-bootstrap --enable-shared --enable-threads=posix --enable-checking=release --with-system-zlib --enable-__cxa_atexit --disable-libunwind-exceptions --enable-gnu-unique-object --enable-languages=c,c++,objc,obj-c++,java,fortran,ada --enable-java-awt=gtk --disable-dssi --with-java-home=/usr/lib/jvm/java-1.5.0-gcj-1.5.0.0/jre --enable-libgcj-multifile --enable-java-maintainer-mode --with-ecj-jar=/usr/share/java/eclipse-ecj.jar --disable-libjava-multilib --with-ppl --with-cloog --with-tune=generic --with-arch_32=i686 --build=x86_64-redhat-linux
Thread model: posix
gcc version 4.4.7 20120313 (Red Hat 4.4.7-4) (GCC)


When compiling your code I get:
flip3 ~/public_html/assignment3 157% g++ -std=c++0x test.cpp -o test.cpp
test.cpp:11: error: expected ‘;’ before ‘override’
test.cpp:12: error: expected ‘;’ before ‘}’ token
test.cpp:16: error: expected ‘;’ before ‘override’
test.cpp:17: error: expected ‘;’ before ‘}’ token
test.cpp: In function ‘int main()’:
test.cpp:23: error: ‘nullptr’ was not declared in this scope


So with that info it looks like a version issue with g++. Unfortunately, this is not something I have control over.

Well, it appears that that version of G++ is too old to have complete compatibility (it was released barely a year after C++11 became official, and the only changes were a few bug fixes). On a side note, why are you compiling it on top of itself?

Regardless, here is the same thing, without using C++11 options:
1
2
3
4
5
6
7
8
9
combatant* combatant1 = 0;  // 0 instead of nullptr, raw pointers
if (menu == 1)
    combatant1 = new warrior;
if (menu == 2)
    combatant1 = new ranger;

// when ending, resetting or changing, remember to do this:
delete combatant1;
combatant1 = 0;


EDIT:
Actually, I just remembered - there is another option, which is to use the Boost libraries ( www.boost.org ). They provide std::shared_ptr and std::unique_ptr, as well as most of the other C++11 libraries (considering they came from Boost originally) in a cross compiler way. I'm pretty sure it supports down to G++3.4.
Last edited on
Oh I was compiling on itself because oops.... Just going to fast there.

Man, how do you keep versions straight?

Anyway, the version there compiles well until it hits my combat function where I pass the objects as a reference... it always has to be something doesn't it?
void combat (combatant &comb1, combatant &comb2) { stuff;}
assignment3.cpp: In function ‘int main()’:
assignment3.cpp:255: error: invalid initialization of reference of type ‘combatant&’ from expression of type ‘combatant*’
assignment3.cpp:156: error: in passing argument 1 of ‘void combat(combatant&, combatant&)’
make: *** [assignment3] Error 1

I am wondering if I'll need a different way to pass these when using the above method.
In that case, you will need to either change the functions so that it takes a pointer instead of a reference, or dereference the pointer every time you send it to one of your functions. You can't do a reference straight off though (without some little hacks), because you cannot change what a reference points to. It is possible, though, so if you really want it as a reference that is fine.
Yeah, there we go. Thanks a ton NT3 for sticking with me through this.

Lessons learned... man I gotta get them to upgrade that g++!

Topic archived. No new replies allowed.