views:

312

answers:

3

why isnt my object being created? When I do it like so, I am told error C2065: 'AllReferrals' : undeclared identifier as well as error C2228: left of '.push_back' must have class/struct/union.
If I put the list initialization before the class I get error C2065: 'AllReferrals' : undeclared identifier.
Thanks!

#include <iostream>
#include <fstream>
#include <regex>
#include <string>
#include <list>
#include <map>

using namespace std;
using namespace tr1;

class Referral
{
public:
 string url;
 map<string, int> keywords;

 static bool submit(string url, string keyword, int occurrences)
 {
  //if(lots of things i'll later add){
   Referral(url, keyword, occurrences);
   return true;
  //}
  //else
  // return false;
 }

private:
 list<string> urls;

 Referral(string url, string keyword, int occurrences)
 {
  url = url;
  keywords[keyword] = occurrences;
  AllReferrals.push_back(this);
 }
};

static list<Referral> AllReferrals;

int main()
{
 Referral::submit("url", "keyword", 1);
 cout << AllReferrals.size();
 cout << "\n why does that ^^ say 0  (help me make it say one)?";
 cout << "\n and how can i AllReferrals.push_back(this) from my constructor?";
 cout << " When I do it like so, I am told  error C2065: 'AllReferrals' : undeclared identifier";
 cout << " as well as error C2228: left of '.push_back' must have class/struct/union.";
 cout << " If I put the list initialization before the class I get error C2065: 'AllReferrals' : undeclared identifier.";
 cout << "\n\n\t Thanks!";
 getchar();
}
+3  A: 

AllReferrals name have to be declared before it's use when you read the file from top to bottom.

If not declared, the compiler don't know that it exists. That's what the error say.

To fix your problem, just move the declaration before it's use and use "forward declaration" for the type that you need a name for but is not defined yet.

#include <iostream>
#include <fstream>
#include <regex>
#include <string>
#include <list>
#include <map>

using namespace std;
using namespace tr1;

class Referral; // forward declaration
list<Referral> AllReferrals; // here 'static' is not needed

class Referral
{
public:
 string url;
 map<string, int> keywords;

 static bool submit(string url, string keyword, int occurrences)
 {
  //if(lots of things i'll later add){
   Referral(url, keyword, occurrences);
   return true;
  //}
  //else
  // return false;
 }

private:
 list<string> urls;

 Referral(string url, string keyword, int occurrences)
 {
  url = url;
  keywords[keyword] = occurrences;
  AllReferrals.push_back(this);
 }
};


int main()
{
 Referral::submit("url", "keyword", 1);
 cout << AllReferrals.size();
 cout << "\n why does that ^^ say 0  (help me make it say one)?";
 cout << "\n and how can i AllReferrals.push_back(this) from my constructor?";
 cout << " When I do it like so, I am told  error C2065: 'AllReferrals' : undeclared identifier";
 cout << " as well as error C2228: left of '.push_back' must have class/struct/union.";
 cout << " If I put the list initialization before the class I get error C2065: 'AllReferrals' : undeclared identifier.";
 cout << "\n\n\t Thanks!";
 getchar();
}

As commenters added, another solution would be to move the constructor definition under the AllReferrals definition. Anyway it's always a name apparition order problem.

Klaim
+1: ... move the contructor implementation below the definition of the list.
David Rodríguez - dribeas
Also should be `AllReferrals.push_back(*this);`
pingw33n
i also needed to dereference my object, so push_back(*this);
Nona Urbiz
haha, didnt see that ping, thanks! but i just figured it out myself :)
Nona Urbiz
pinggw33n>yes just figured that, will add.dribeas> Ah yes you're right, adding that too.
Klaim
+1  A: 

Try something more like this:

...

class Referral;

static list<Referral> AllReferrals;

class Referral
{
...
};
simon
+2  A: 

Your first problem is that AllReferrals must be declared before you can use it. However, the Referral class must be defined before your declaration of AllReferrals. You can solve this by splitting the declaration and definition of the Referral constructor, like so:

.
.
.
    Referral(string url, string keyword, int occurrences); // declaration
};

static list<Referral> AllReferrals;

Referral::Referral(string url, string keyword, int occurrences) // definition
{
    url = url;
    keywords[keyword] = occurrences;
    AllReferrals.push_back(this);
}
.
.
.

Then you need to realise that this is a pointer, and you have declared your list to store actual object data. You can solve this in two ways:

  • change AllReferrals.push_back(this); to AllReferrals.push_back(*this);. This will cause a copy of the object to be placed on the list, which will Just Work but may have performance implications.

  • change the declaration of static list<Referral> AllReferrals; to static list<Referral *> AllReferrals;. This on its own will not give you working code, since Referral is being created on the locally in submit() and when you leave submit() the object will be discarded and the pointer left dangling. You can change Referral(url, keyword, occurrences); in submit() to new Referral(url, keyword, occurrences); which will cause the object to persist until deleted; but you must then make sure you delete all the Referral objects you created in this way when you are done with them, or you will leak memory - not permanently, the OS will clean up after you when your application termiantes, but it may cause you problems if you are planning on creating lots of them.

moonshadow
+1, It is sad when people ask but do not read answers... this exact same corrections you have just posted were posted by me in a previous question. Maybe if enough people insist on it...
David Rodríguez - dribeas
I'm sorry, I did not understand it in that context. Here it helped me. Why is there a problem with that?
Nona Urbiz