Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game. |
Notices |
Welcome to LinuxQuestions.org, a friendly and active Linux Community.
You are currently viewing LQ as a guest. By joining our community you will have the ability to post topics, receive our newsletter, use the advanced search, subscribe to threads and access many other special features. Registration is quick, simple and absolutely free. Join our community today!
Note that registered members see fewer ads, and ContentLink is completely disabled once you log in.
Are you new to LinuxQuestions.org? Visit the following links:
Site Howto |
Site FAQ |
Sitemap |
Register Now
If you have any problems with the registration process or your account login, please contact us. If you need to reset your password, click here.
Having a problem logging in? Please visit this page to clear all LQ-related cookies.
Get a virtual cloud desktop with the Linux distro that you want in less than five minutes with Shells! With over 10 pre-installed distros to choose from, the worry-free installation life is here! Whether you are a digital nomad or just looking for flexibility, Shells can put your Linux machine on the device that you want to use.
Exclusive for LQ members, get up to 45% off per month. Click here for more info.
|
|
|
04-24-2007, 10:39 PM
|
#1
|
Senior Member
Registered: Jan 2006
Location: Charleston, SC, USA
Distribution: Debian, Gentoo, Ubuntu, RHEL
Posts: 1,148
Rep:
|
Silly C++ Question
Okay, so I started to learn to program a few years ago in C++. I couldn't get my head around OO, so I went to C, where I've done most of my work. Through my University, I've also done some work in Java, so I fear that I'm falling prey to a subtle syntactical difference.
I define the following class:
Code:
class Preferences{
private:
static GHashTable* thePrefs;
static char *localLoc;
static char *globalLoc;
public:
//Bunch of methods
};
Everything in the class is declared static. The class is designed to encapsulate the user preferences for an application, allowing other parts of the app a simple, consistent way of accessing the settings.
My trouble is that I declare a number of static methods, and every single reference of any of my static data members in any of those methods triggers this error:
Code:
test.cpp:(.text+0x9e): undefined reference to `Preferences::thePrefs'
except with the variable name referring to whichever variable I tried to access.
Yes, I am directly using the C glib rather than glibmm. I just learned glib in C, and would prefer it that way. Could that cause any problems? It still gives me this trouble when all the static variables are primitives.
|
|
|
04-24-2007, 10:52 PM
|
#2
|
Senior Member
Registered: Jan 2005
Location: Canada
Distribution: ubuntu
Posts: 2,539
Rep:
|
could you post the complete code of the class?
|
|
|
04-24-2007, 10:55 PM
|
#3
|
Senior Member
Registered: Jan 2006
Location: Charleston, SC, USA
Distribution: Debian, Gentoo, Ubuntu, RHEL
Posts: 1,148
Original Poster
Rep:
|
It's rough, probably pre-pre-pre alpha.
I get the same errors if I comment any of the functions totally out of the code, so it's not any one function causing it.
Preferences.h
Code:
#include <glib.h>
class Preferences
{
public:
static char* lookupKey(char*);
static void storeKey(char*, char*);*/
static void initialize();
/*TODO Adapt File I/O to VFS if/when one is implemented*/
static gboolean loadFromFiles(char* global, char* local);
static gboolean reloadFromFiles();*/
private:
static GHashTable* thePrefs;
static char *localLoc;
static char *globalLoc;
};
Preferences.cpp
Code:
#include <string.h>
#include "Preferences.h"
void Preferences::initialize()
{
thePrefs = g_hash_table_new_full((GHashFunc)g_str_hash, (GEqualFunc)strcmp,
(GDestroyNotify)g_free, (GDestroyNotify)g_free);
localLoc = NULL;
globalLoc = NULL;
}
char* Preferences::lookupKey(char* theKey)
{
return (char*) g_hash_table_lookup(thePrefs, theKey);
}
void Preferences::storeKey(char* theKey, char* theData)
{
g_hash_table_insert(thePrefs, g_strdup(theKey), g_strdup(theData));
}
gboolean Preferences::loadFromFiles(char* global, char* local)
{
GKeyFile* globalKeys = g_key_file_new();
GKeyFile* localKeys = g_key_file_new();
char** keys;
char** tmp;
gboolean rtnVal = g_key_file_load_from_file(globalKeys, global,
G_KEY_FILE_NONE, NULL);
char* groupName;
gboolean localWorked;
if(rtnVal)
{
groupName = g_key_file_get_start_group(globalKeys);
keys = g_key_file_get_keys(globalKeys,
groupName,NULL,
NULL);
tmp = keys;
while(*tmp)
{
g_hash_table_insert(thePrefs, g_strdup(*tmp),
g_strdup(g_key_file_get_value(globalKeys ,groupName,
*tmp, NULL)));
tmp++;
}
g_strfreev(keys);
}
g_key_file_free(globalKeys);
localWorked = g_key_file_load_from_file(localKeys, local, G_KEY_FILE_NONE,
NULL);
rtnVal = rtnVal || localWorked;
if(localWorked)
{
groupName = g_key_file_get_start_group(localKeys);
keys = g_key_file_get_keys(localKeys,
groupName,NULL,
NULL);
tmp = keys;
while(*tmp)
{
g_hash_table_insert(thePrefs, g_strdup(*tmp),
g_strdup(g_key_file_get_value(localKeys,groupName,
*tmp, NULL)));
tmp++;
}
g_strfreev(keys);
}
g_key_file_free(localKeys);
if(localLoc)
g_free(localLoc);
if(globalLoc)
g_free(globalLoc);
localLoc = g_strdup(local);
globalLoc = g_strdup(global);
return rtnVal;
}
gboolean Preferences::reloadFromFiles()
{
return loadFromFiles(globalLoc, localLoc);
}
Last edited by PatrickNew; 04-24-2007 at 11:26 PM.
|
|
|
04-24-2007, 11:16 PM
|
#4
|
Senior Member
Registered: Jan 2005
Location: Canada
Distribution: ubuntu
Posts: 2,539
Rep:
|
what command did you use when you compiled it? (so i can try the same and attempt to debug)
Last edited by nadroj; 04-24-2007 at 11:32 PM.
|
|
|
04-24-2007, 11:25 PM
|
#5
|
Senior Member
Registered: Jan 2006
Location: Charleston, SC, USA
Distribution: Debian, Gentoo, Ubuntu, RHEL
Posts: 1,148
Original Poster
Rep:
|
g++ `pkg-config --cflags --libs glib-2.0` -o test test.cpp
So I'm including the test file, which doesn't do much of anything.
Code:
#include "Preferences.cpp"
#include <iostream>
using namespace std;
int main(int argc, char** argv)
{
Preferences::initialize();
}
|
|
|
04-25-2007, 12:01 AM
|
#6
|
Senior Member
Registered: Jan 2005
Location: Canada
Distribution: ubuntu
Posts: 2,539
Rep:
|
i havent worked in C++ in a long time this is why im so confused! also, ive never made a class (in C++) like you are trying to, with all the statics, i mean.
ok, adding these lines to Preferences.cpp just after the includes seems to allow it to compile (dont know why though):
Code:
GHashTable* Preferences::thePrefs;
char* Preferences::localLoc;
char* Preferences::globalLoc;
|
|
|
04-25-2007, 12:08 AM
|
#7
|
Senior Member
Registered: Jan 2006
Location: Charleston, SC, USA
Distribution: Debian, Gentoo, Ubuntu, RHEL
Posts: 1,148
Original Poster
Rep:
|
Allright, I give that a try and see what comes up in testing. Seems so odd, it feels like that should fail to compile because we're redefining variables. Well, thanks for your help!
|
|
|
04-25-2007, 12:11 AM
|
#8
|
Senior Member
Registered: Jan 2005
Location: Canada
Distribution: ubuntu
Posts: 2,539
Rep:
|
it seems that way, i know. if you get rid of the 'Preferences::' it will give you that error. this just must be some extra step you have to do when you have this situation.
my guess is that its 'reminding' the compiler about the private static variables that really exist in that class.
|
|
|
04-25-2007, 12:29 AM
|
#9
|
Member
Registered: Sep 2006
Distribution: open SuSE 10.0
Posts: 116
Rep:
|
For static member variable, you should redefine it in the source .cpp
So, for your Preferences.cpp, you should add (the bold ones)
Code:
#include <string.h>
#include "Preferences.h"
GHashTable* Preferences::thePrefs;
char * Preferences::localLoc;
char * Preferences::globalLoc;
void Preferences::initialize()
{
thePrefs = g_hash_table_new_full((GHashFunc)g_str_hash, (GEqualFunc)strcmp,
(GDestroyNotify)g_free, (GDestroyNotify)g_free);
localLoc = NULL;
globalLoc = NULL;
}
char* Preferences::lookupKey(char* theKey)
{
return (char*) g_hash_table_lookup(thePrefs, theKey);
}
void Preferences::storeKey(char* theKey, char* theData)
{
g_hash_table_insert(thePrefs, g_strdup(theKey), g_strdup(theData));
}
gboolean Preferences::loadFromFiles(char* global, char* local)
{
GKeyFile* globalKeys = g_key_file_new();
GKeyFile* localKeys = g_key_file_new();
char** keys;
char** tmp;
gboolean rtnVal = g_key_file_load_from_file(globalKeys, global,
G_KEY_FILE_NONE, NULL);
char* groupName;
gboolean localWorked;
if(rtnVal)
{
groupName = g_key_file_get_start_group(globalKeys);
keys = g_key_file_get_keys(globalKeys,
groupName,NULL,
NULL);
tmp = keys;
while(*tmp)
{
g_hash_table_insert(thePrefs, g_strdup(*tmp),
g_strdup(g_key_file_get_value(globalKeys ,groupName,
*tmp, NULL)));
tmp++;
}
g_strfreev(keys);
}
g_key_file_free(globalKeys);
localWorked = g_key_file_load_from_file(localKeys, local, G_KEY_FILE_NONE,
NULL);
rtnVal = rtnVal || localWorked;
if(localWorked)
{
groupName = g_key_file_get_start_group(localKeys);
keys = g_key_file_get_keys(localKeys,
groupName,NULL,
NULL);
tmp = keys;
while(*tmp)
{
g_hash_table_insert(thePrefs, g_strdup(*tmp),
g_strdup(g_key_file_get_value(localKeys,groupName,
*tmp, NULL)));
tmp++;
}
g_strfreev(keys);
}
g_key_file_free(localKeys);
if(localLoc)
g_free(localLoc);
if(globalLoc)
g_free(globalLoc);
localLoc = g_strdup(local);
globalLoc = g_strdup(global);
return rtnVal;
}
gboolean Preferences::reloadFromFiles()
{
return loadFromFiles(globalLoc, localLoc);
}
EDIT: Oops, didn't realize that nadroj has answered it before.
Last edited by g4j31a5; 04-25-2007 at 12:32 AM.
|
|
|
04-25-2007, 07:37 AM
|
#10
|
Senior Member
Registered: Jan 2006
Location: Charleston, SC, USA
Distribution: Debian, Gentoo, Ubuntu, RHEL
Posts: 1,148
Original Poster
Rep:
|
out of curiosity, is this true in general or is it just what I have to do to get this to compile? Redefining static member variables that is?
|
|
|
04-25-2007, 01:38 PM
|
#11
|
Senior Member
Registered: Mar 2005
Location: USA::Pennsylvania
Distribution: Slackware
Posts: 1,065
Rep:
|
Quote:
Originally Posted by PatrickNew
out of curiosity, is this true in general or is it just what I have to do to get this to compile? Redefining static member variables that is?
|
in general
|
|
|
04-25-2007, 05:07 PM
|
#12
|
Senior Member
Registered: Nov 2005
Location: Hanoi
Distribution: Fedora 13, Ubuntu 10.04
Posts: 2,379
Rep:
|
As an aside I get the feeling that your class is not really following the OO paradigm. If as I understand everything is static then really you should change the class to be a singleton class. There are lots of tutorials on the web explaining this. I would recommend looking at that and on the way learn a little more about the "OO way"
|
|
|
04-25-2007, 06:37 PM
|
#13
|
Senior Member
Registered: Jan 2006
Location: Charleston, SC, USA
Distribution: Debian, Gentoo, Ubuntu, RHEL
Posts: 1,148
Original Poster
Rep:
|
Well, the class really isn't very OO due to the nature of its task - that is one application should never have multiple sets of settings at one time. So, I guess the non-OOness is intentional. But I will look into singleton clasees, and thanks for the tip!
|
|
|
04-25-2007, 06:55 PM
|
#14
|
Senior Member
Registered: Jan 2006
Location: Charleston, SC, USA
Distribution: Debian, Gentoo, Ubuntu, RHEL
Posts: 1,148
Original Poster
Rep:
|
Wow, a singleton class is *exactly* what I really wanted. Thanks!
|
|
|
04-25-2007, 10:48 PM
|
#15
|
Senior Member
Registered: Jan 2006
Location: Charleston, SC, USA
Distribution: Debian, Gentoo, Ubuntu, RHEL
Posts: 1,148
Original Poster
Rep:
|
Many thanks to all. I did actually convert to a singleton design and it turned out to be a smaller, cleaner solution that looks as though it will be more maintainable.
|
|
|
All times are GMT -5. The time now is 03:42 AM.
|
LinuxQuestions.org is looking for people interested in writing
Editorials, Articles, Reviews, and more. If you'd like to contribute
content, let us know.
|
Latest Threads
LQ News
|
|