By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
425,992 Members | 934 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 425,992 IT Pros & Developers. It's quick & easy.

Non static function needs acces to static datamembers

P: 21
Hi,

I have the following problem:
I am trying to make some sort of base class menu that i can then use to derive other menu's from. Those menu's should then be able to interact with each other.
And, i have most of the idea figured out and I thought out how i want to do it. But when i started coding i found a slight... difficulty.
It might be easy to overcome, but google let me down :( and my own imagination made one happy jump, but well, that didn't do the trick either.

So, the problem is this:
My class API_MENU_BASIC (yes, it really is a bad name, inspiration lacks me when it comes to names ) has following vectors:
Expand|Select|Wrap|Line Numbers
  1. /* Menu choices */
  2. /** A vector containing all possible MENU's and their descriptions. */
  3. static vector<pair<API_MENU_BASIC*, string> > fMenus;
  4. static bool fMenus_set; /**< fMenu's has already been set. */
  5.  
  6. /** Vector containing all the valid choices for the menu class. 
  7.  * It might be that a class can not acces all of the menu's in fMenus. 
  8.  * A class will thus, always acces them through the fChoices vector. */
  9. vector<int> fChoices;
  10. bool fChoices_set; /**< fChoices has been set. */
The first vector is an array holding all the menu's (derived from API_MENU_BASIC) that are being used, and their respective description.
This vector may also be initialized only once, that's where the static bool fMenus_set is for.

The second vector keeps track of what are valid menu choices for each derived class. Because it is very well possible that a derived class can only access a 'print' menu and none of the 'modify' menu's.
(This vector may also be initialized only once, again, fChoices_set )

Both vectors have an 'initialization' function.
Expand|Select|Wrap|Line Numbers
  1. /* Build menu's */
  2. static void setMenus( const vector<pair<API_MENU_BASIC*, string> >& );
  3. void setChoices( const vector<int>& );
The problem isn't here though.

Now, where the problem really is:
The menu navigators:
Expand|Select|Wrap|Line Numbers
  1. /* Menu navigators */
  2. void expand( const int id );
  3. virtual void open() = 0;
  4.  
Now what expand has to do is the following:
It gets the object with given index from the fMenus (static :S) vector and 'loads' it onto the
Expand|Select|Wrap|Line Numbers
  1. /**
  2. * Menu pointer: When we expand a new menu, the menu will first be loaded
  3.  * onto the fActive field and then opened.
  4.  */
  5. API_MENU_BASIC* fActive;
  6.  
fActive pointer. Then we will fActive->open() the menu.

This is the implementation for the expand function:
Expand|Select|Wrap|Line Numbers
  1. /** Run the menu that is associated with index 'id' in the
  2.  * vector of valid choices.
  3.  * @param    id        Selected choice
  4.  * @return    void
  5.  * @exception        none
  6.  */
  7. void API_MENU_BASIC::expand( const int id ){
  8.     fActive = fMenus[fChoices[id]].first;
  9.     fActive->open();
  10. }
  11.  
So, it sort of has to be both static and non static as it has to access both menu's :S. I tried solving this using a static functions (as open also needs access to both ):
Expand|Select|Wrap|Line Numbers
  1. /* Menu inspectors */
  2. static API_MENU_BASIC* getMenu( const int& id );
  3. static string& getDescription( const int& id );
  4.  
These two methods should then just acces the static fMenu vector and return whatever is needed to the poor non static functions that need access to fMenu.

Now the compiler doesn't like me for what i'm trying, it's just, i don't know what it is that i'm doing wrong. And, I don't dare say this but, i didn't even find any usefull information in Strousstrup :(. Which is most probably my bad, but, alas. I didn't find it.
The compiler errors i'm getting are:
- When i try to make getMenu, getDescription and setMenus static:
API_MENU_BASIC.cpp:49: error: cannot declare member function ‘static void MENU::API_MENU_BASIC::setMenus(const std::vector<std::pair<MENU::API_MENU_BASIC*, std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<MENU::API_MENU_BASIC*, std::basic_string<char, std::char_traits<char>, std::allocator<char> > > > >&)’ to have static linkage
API_MENU_BASIC.cpp:78: error: cannot declare member function ‘static MENU::API_MENU_BASIC* MENU::API_MENU_BASIC::getMenu(const int&)’ to have static linkage
API_MENU_BASIC.cpp:88: error: cannot declare member function ‘static std::string& MENU::API_MENU_BASIC::getDescription(const int&)’ to have static linkage

And when i don't make them static he sais that fMenus isn't in scope.

Any help with this would be enormously appreciated, i have no idea how to fix this.
Thanks in advance

-Tom
Jan 2 '08 #1
Share this Question
Share on Google+
3 Replies


weaknessforcats
Expert Mod 5K+
P: 9,197
API_MENU_BASIC.cpp:49: error: cannot declare member function ‘static void MENU::API_MENU_BASIC::setMenus(const std::vector<std::pair<MENU::API_MENU_BASIC*, std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<MENU::API_MENU_BASIC*, std::basic_string<char, std::char_traits<char>, std::allocator<char> > > > >&)’ to have static linkage
Let's see what you have on line 49 of API_MENU_BASIC.cpp plus the class declarations. I want you see your inheritance design.

Anytime I see static I suspect a design problem since static is used for only very specific purposes.

Plus, if you vector can only be initialized once, then it need to be a implamented as Singleton. Read this article: http://www.thescripts.com/forum/thread656124.html.

Plus the menu choices should be partof the menu object and not in another vector.

Please post again.
Jan 3 '08 #2

P: 21
Hi,

thanks for the reply :).
I don't have an inheritance design yet, as i was only developing the base class.
The classes that do inherit the base class would only need to have the open() function reďmplemented.
As open() would then see what menu to print and what to do with the output handed to it. (It's for a console application).

And you're probably right, i do need a singleton. It makes sense, i just had never heared of it before, so static was the only thing that popped into my mind.
Anyway, this is the entire header file:
Expand|Select|Wrap|Line Numbers
  1. /**
  2.  * Menu base class.
  3.  * @file    API_MENU_BASIC.h
  4.  * @author    Tom
  5.  */
  6.  
  7. #ifndef API_MENU_BASIC_H
  8. #define API_MENU_BASIC_H
  9.  
  10. #include <map>
  11. #include <string>
  12. #include <vector>
  13. using std::vector;
  14. using std::pair;
  15. using std::string;
  16.  
  17. namespace MENU{
  18.  
  19.     class API_MENU_BASIC {
  20.         protected:
  21.             /* Menu choices */
  22.             /** A vector containing all possible MENU's and their descriptions. */
  23.             static vector<pair<API_MENU_BASIC*, string> > fMenus;
  24.             static bool fMenus_set; /**< fMenu's has already been set. */
  25.  
  26.             /** Vector containing all the valid choices for the menu class. 
  27.              * It might be that a class can not acces all of the menu's in fMenus. 
  28.              * A class will thus, always acces them through the fChoices vector. */
  29.             vector<int> fChoices;
  30.             bool fChoices_set; /**< fChoices has been set. */
  31.  
  32.             /**
  33.              * Menu pointer: When we expand a new menu, the menu will first be loaded
  34.              * onto the fActive field and then opened.
  35.              */
  36.             API_MENU_BASIC* fActive; 
  37.  
  38.             /* Menu inspectors */
  39.             static API_MENU_BASIC* getMenu( const int& id );
  40.             static string& getDescription( const int& id );
  41.         public:
  42.             /* ctor and dtor */
  43.             API_MENU_BASIC();
  44.             virtual ~API_MENU_BASIC();
  45.  
  46.             /* Menu navigators */
  47.             void expand( const int id );
  48.             virtual void open() = 0;    
  49.  
  50.             /* Build menu's */
  51.             static void setMenus( const vector<pair<API_MENU_BASIC*, string> >& );
  52.             void setChoices( const vector<int>& );
  53.  
  54.     };
  55.  
  56. } //Namespace MENU
  57. #endif //API_MENU_BASIC_H
  58.  
The implementation file:
Expand|Select|Wrap|Line Numbers
  1. /**
  2.  * @file    API_MENU_BASIC.cpp
  3.  * @author    Tom 
  4.  */
  5.  
  6. #include "API_MENU_BASIC.h"
  7.  
  8. namespace MENU{
  9.  
  10.     /* Initializing static members */
  11.     bool API_MENU_BASIC::fMenus_set = false;
  12.     Recipe* API_MENU_BASIC::fRecipe = 0;
  13.     CookBook* API_MENU_BASIC::fBook = 0;
  14.     Library* API_MENU_BASIC::fLib = 0;
  15.  
  16.     /* ctor & dtor */
  17.  
  18.     /** Constructor: initializes non-static datamembers */
  19.     API_MENU_BASIC::API_MENU_BASIC()
  20.     : fChoices_set( false ), fActive( 0 )
  21.     {
  22.  
  23.     }
  24.  
  25.     /** Destructor */
  26.     API_MENU_BASIC::~API_MENU_BASIC(){}
  27.  
  28.     /* Menu navigators */
  29.  
  30.     /** Run the menu that is associated with index 'id' in the
  31.      * vector of valid choices.
  32.      * @param    id        Selected choice
  33.      * @return    void
  34.      * @exception        none
  35.      */
  36.     void API_MENU_BASIC::expand( const int id ){
  37.         fActive = getMenu(fChoices[id]);
  38.         fActive->open();
  39.     }
  40.  
  41.     /* Build Menus */
  42.  
  43.     /** Initialize the valid menu's and their descriptions.
  44.      * This function only has effect if the menu's haven't been initialized yet!
  45.      * @param    menus    Vector containing the menu information.
  46.      * @return     void
  47.      * @exception        none
  48.      */
  49.     static void API_MENU_BASIC::setMenus( const vector<pair<API_MENU_BASIC*, string> >& menus ){
  50.         if( !fMenus_set ){
  51.             fMenus = menus;
  52.             fMenus_set = true;
  53.         }
  54.     }
  55.  
  56.     /** Initialize the choices a certain menu class has. It may be that the class
  57.      * can not acces all of the menu choices in the fMenus vector.
  58.      * This function only has effect if the choices haven't been initialized yet!
  59.      * @param    choices    Vector containing the valid choice information
  60.      * @return     void
  61.      * @exception        none
  62.      */
  63.     void API_MENU_BASIC::setChoices( const vector<int>& choices ){
  64.         if( !fChoices_set ){
  65.             fChoices = choices;
  66.             fChoices_set = true;
  67.         }
  68.     }
  69.  
  70.     /* Menu Inspectors */
  71.  
  72.     /** Non static member functions can get the menu's out of fMenu's using
  73.      * this function.
  74.      * @param    id                    index of the member function
  75.      * @return    API_MENU_BASIC*        menu at index 'id'
  76.      * @exception                    none
  77.      */
  78.     static API_MENU_BASIC* API_MENU_BASIC::getMenu( const int& id ){
  79.         return fMenus[id].first;
  80.     }
  81.  
  82.     /** Non static member functions can get the descriptions out of fMenu's using
  83.      * this function.
  84.      * @param    id            index of the member function
  85.      * @return    string&        description at index 'id'
  86.      * @exception            none
  87.      */
  88.     static string& API_MENU_BASIC::getDescription( const int& id ){
  89.         return fMenus[id].second;
  90.     }
  91.  
  92. } //Namespace MENU
  93.  
Do note , this code doesn't compile. Because i'm making those functions static.
Which, can't be static.

Though, i didn't really know static functions were available even when the object wasn't created so, there might be a LOT more of that kind of errors in this, for you guys most likely very simple code.
I've still got a loooot to learn. This code has a loooot of flaws, and probably a thousand and one things that can be done ten times better. All sugestions are more than welcome.

Which brings me to my next point actually, could you suggest me any books on designing and design patters ?
Is "Design Patterns by Erich Fromm, et al, Addison-Wesley 1994." a good book ? It's one you refer to in the singleton how-to.
Another thing i'd like to know. Would you know any good source code (maybe from an opensource program?) to check out, to read and try to understand so i can learn a bit from it ? I've always found that reading other people's code can be very good learning experience. See how they do it.
I'm kind of looking for source that's not using to difficult libraries ? It might be something simple, implemented in a professional way or something.


Thanks a lot in advance!
-Tom
Jan 4 '08 #3

weaknessforcats
Expert Mod 5K+
P: 9,197
Is "Design Patterns by Erich Fromm, et al, Addison-Wesley 1994." a good book ? It's one you refer to in the singleton how-to.
It OK if you already know C++. This is the pioneer Design Patterns book. There are many out know with other patterns that have been discovered. All a design pattern is a name for a solution of a commonly encountered programming dilemma. Like: How can my object appear to change its type (State). How can my object appear to have methods and data not in the class (Decorator) or (Visitor). How can I know if an object changes wthout having any code to detect this (Observer).

The design pattern you need to design your menu system is the Template Method.

You might read up on that and then re-post. Your current approach is a dead-end.
Jan 4 '08 #4

Post your reply

Sign in to post your reply or Sign up for a free account.