LinuxQuestions.org
Review your favorite Linux distribution.
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
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


Reply
  Search this Thread
Old 04-24-2007, 10:39 PM   #1
PatrickNew
Senior Member
 
Registered: Jan 2006
Location: Charleston, SC, USA
Distribution: Debian, Gentoo, Ubuntu, RHEL
Posts: 1,148
Blog Entries: 1

Rep: Reputation: 48
Thumbs up 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.
 
Old 04-24-2007, 10:52 PM   #2
nadroj
Senior Member
 
Registered: Jan 2005
Location: Canada
Distribution: ubuntu
Posts: 2,539

Rep: Reputation: 60
could you post the complete code of the class?
 
Old 04-24-2007, 10:55 PM   #3
PatrickNew
Senior Member
 
Registered: Jan 2006
Location: Charleston, SC, USA
Distribution: Debian, Gentoo, Ubuntu, RHEL
Posts: 1,148

Original Poster
Blog Entries: 1

Rep: Reputation: 48
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.
 
Old 04-24-2007, 11:16 PM   #4
nadroj
Senior Member
 
Registered: Jan 2005
Location: Canada
Distribution: ubuntu
Posts: 2,539

Rep: Reputation: 60
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.
 
Old 04-24-2007, 11:25 PM   #5
PatrickNew
Senior Member
 
Registered: Jan 2006
Location: Charleston, SC, USA
Distribution: Debian, Gentoo, Ubuntu, RHEL
Posts: 1,148

Original Poster
Blog Entries: 1

Rep: Reputation: 48
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();
}
 
Old 04-25-2007, 12:01 AM   #6
nadroj
Senior Member
 
Registered: Jan 2005
Location: Canada
Distribution: ubuntu
Posts: 2,539

Rep: Reputation: 60
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;
 
Old 04-25-2007, 12:08 AM   #7
PatrickNew
Senior Member
 
Registered: Jan 2006
Location: Charleston, SC, USA
Distribution: Debian, Gentoo, Ubuntu, RHEL
Posts: 1,148

Original Poster
Blog Entries: 1

Rep: Reputation: 48
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!
 
Old 04-25-2007, 12:11 AM   #8
nadroj
Senior Member
 
Registered: Jan 2005
Location: Canada
Distribution: ubuntu
Posts: 2,539

Rep: Reputation: 60
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.
 
Old 04-25-2007, 12:29 AM   #9
g4j31a5
Member
 
Registered: Sep 2006
Distribution: open SuSE 10.0
Posts: 116

Rep: Reputation: 15
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.
 
Old 04-25-2007, 07:37 AM   #10
PatrickNew
Senior Member
 
Registered: Jan 2006
Location: Charleston, SC, USA
Distribution: Debian, Gentoo, Ubuntu, RHEL
Posts: 1,148

Original Poster
Blog Entries: 1

Rep: Reputation: 48
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?
 
Old 04-25-2007, 01:38 PM   #11
xhi
Senior Member
 
Registered: Mar 2005
Location: USA::Pennsylvania
Distribution: Slackware
Posts: 1,065

Rep: Reputation: 45
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
 
Old 04-25-2007, 05:07 PM   #12
graemef
Senior Member
 
Registered: Nov 2005
Location: Hanoi
Distribution: Fedora 13, Ubuntu 10.04
Posts: 2,379

Rep: Reputation: 148Reputation: 148
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"
 
Old 04-25-2007, 06:37 PM   #13
PatrickNew
Senior Member
 
Registered: Jan 2006
Location: Charleston, SC, USA
Distribution: Debian, Gentoo, Ubuntu, RHEL
Posts: 1,148

Original Poster
Blog Entries: 1

Rep: Reputation: 48
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!
 
Old 04-25-2007, 06:55 PM   #14
PatrickNew
Senior Member
 
Registered: Jan 2006
Location: Charleston, SC, USA
Distribution: Debian, Gentoo, Ubuntu, RHEL
Posts: 1,148

Original Poster
Blog Entries: 1

Rep: Reputation: 48
Wow, a singleton class is *exactly* what I really wanted. Thanks!
 
Old 04-25-2007, 10:48 PM   #15
PatrickNew
Senior Member
 
Registered: Jan 2006
Location: Charleston, SC, USA
Distribution: Debian, Gentoo, Ubuntu, RHEL
Posts: 1,148

Original Poster
Blog Entries: 1

Rep: Reputation: 48
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.
 
  


Reply


Thread Tools Search this Thread
Search this Thread:

Advanced Search

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
Silly question huble General 5 02-17-2005 02:03 AM
Really silly question... godhugh Linux - Newbie 1 01-04-2005 11:29 AM
Silly Question Crashed_Again Linux - General 21 04-07-2003 05:08 AM
Silly question jeucken Linux - Newbie 1 01-02-2003 08:44 AM
very silly question jayakrishnan Linux - General 12 04-08-2002 04:59 AM

LinuxQuestions.org > Forums > Non-*NIX Forums > Programming

All times are GMT -5. The time now is 03:42 AM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration