Can't access static member var from static method. Why?

M

Markus Dehmann

My ("static") California class has a list of cities, and a static
member function returns true if a certain city is contained:

California::contains("San Francisco"); // true

I implemented it like below, but it does not compile. It gives me some
obscure linker error (see below). What's wrong with my code?

#include <iostream>
#include <map>

class California{
private:
static std::map<std::string, int> cities;
public:
California(){
cities.insert(std::make_pair("San Francisco", 1));
}
static bool contains(std::string city){
return cities.find(city) != cities.end();
}
};

int main(){
if(California::contains("San Francisco")){
std::cout << "SF is in CA!" << std::endl;
}
}

bash-2.05b$ g++ california.cpp
/tmp/ccduZZS6.o(.gnu.linkonce.t._ZN10California8containsESs+0x11): In
function `California::contains(std::basic_string<char,
std::char_traits<char>, std::allocator<char> >)':
: undefined reference to `California::cities'
/tmp/ccduZZS6.o(.gnu.linkonce.t._ZN10California8containsESs+0x2a): In
function `California::contains(std::basic_string<char,
std::char_traits<char>, std::allocator<char> >)':
: undefined reference to `California::cities'
collect2: ld returned 1 exit status
 
J

JKop

Markus Dehmann posted:

#include <iostream>
#include <map>

class California{
private:
static std::map<std::string, int> cities;
public:
California(){
cities.insert(std::make_pair("San Francisco", 1));
}
static bool contains(std::string city){
return cities.find(city) != cities.end();
}
};



int main(){
if(California::contains("San Francisco")){
std::cout << "SF is in CA!" << std::endl;
}
}



Now all is well.


-JKop
 
A

Andreas Schmidt

Markus Dehmann posted:




Now all is well.

You mean, now it compiles. But it does not work as intended: The map is
empty. So, the constructor is actually never called, which actually makes
sense, of course, since I never construct the object. Java has a static{}
block for static initialization. What can I use in C++?

And, I don't want that users of my California class have to declare the
map California::cities. They don't have anything to do with my internal
data structure.

This is the sad output now (code see below):
bash-2.05b$ g++ california.cpp
bash-2.05b$ ./a.out
Number of cities: 0
SF is NOT in CA.

How can I make it right?
Thanks!


#include <iostream>
#include <map>

class California{
private:
static std::map<std::string, int> cities;
public:
California(){
std::cerr << "Constructor called" << std::endl;
cities.insert(std::make_pair("San Francisco", 1));
}
static bool contains(std::string city){
return cities.find(city) != cities.end();
}
static int getSize(){
return cities.size();
}
};

std::map<std::string,int> California::cities;

int main(){
std::cout << "Number of cities: " << California::getSize() <<
std::endl;
if(California::contains("San Francisco")){
std::cout << "SF is in CA!" << std::endl;
}else{
std::cout << "SF is NOT in CA." << std::endl;
}
}
 
A

Andreas Schmidt

[class]
std:map<std::string,int> California::cities;
[int main]

Now all is well.

You mean, now it compiles. But it does not work as intended: The map is
empty. So, the constructor is actually never called, which actually
makes sense, of course, since I never construct the object. Java has a
static{} block for static initialization. What can I use in C++?

And, I don't want that users of my California class have to declare the
map California::cities. They don't have anything to do with my internal
data structure.

This is the sad output now (code see below):
bash-2.05b$ g++ california.cpp
bash-2.05b$ ./a.out
Number of cities: 0
SF is NOT in CA.

How can I make it right?
Thanks!


#include <iostream>
#include <map>

class California{
private:
static std::map<std::string, int> cities;
public:
California(){
std::cerr << "Constructor called" << std::endl;
cities.insert(std::make_pair("San Francisco", 1));
}
static bool contains(std::string city){
return cities.find(city) != cities.end();
}
static int getSize(){
return cities.size();
}
};

std::map<std::string,int> California::cities;

int main(){
std::cout << "Number of cities: " << California::getSize() <<
std::endl;
if(California::contains("San Francisco")){
std::cout << "SF is in CA!" << std::endl;
}else{
std::cout << "SF is NOT in CA." << std::endl;
}
}

Now I think a singleton might be the best way to do this.
 
J

JKop

Andreas Schmidt posted:
Java has a static{} block for static initialization. What can I use
in C++?

Just work with it like any other global variable:

std::map<std::string,int> California::cities( ....... );


-JKop
 
R

red floyd

Andreas said:
You mean, now it compiles. But it does not work as intended: The map is
empty. So, the constructor is actually never called, which actually
makes sense, of course, since I never construct the object. Java has a
static{} block for static initialization. What can I use in C++?

And, I don't want that users of my California class have to declare the
map California::cities. They don't have anything to do with my internal
data structure.

This is the sad output now (code see below):
bash-2.05b$ g++ california.cpp
bash-2.05b$ ./a.out
Number of cities: 0
SF is NOT in CA.

How can I make it right?
Thanks!


#include <iostream>
#include <map>

class California{
private:
static std::map<std::string, int> cities;
public:
California(){
std::cerr << "Constructor called" << std::endl;
cities.insert(std::make_pair("San Francisco", 1));
}
static bool contains(std::string city){
return cities.find(city) != cities.end();
}
static int getSize(){
return cities.size();
}
};

std::map<std::string,int> California::cities;

int main(){
std::cout << "Number of cities: " << California::getSize() <<
std::endl;
if(California::contains("San Francisco")){
std::cout << "SF is in CA!" << std::endl;
}else{
std::cout << "SF is NOT in CA." << std::endl;
}
}

Where did you ever create an object of class California? The only place
that something gets added to California::cities is in the constructor
for California. Since you never construct a California object, it's
perfectly correct (as written) for California::cities to be empty.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,577
Members
45,052
Latest member
LucyCarper

Latest Threads

Top