Archived

This topic is now archived and is closed to further replies.

C++ Classes and namespaces - one problem

This topic is 4947 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hi Question 1. I am confused about one thing. What I was trying to do is to get rid of a class declaration CFoo declared in Foo.h (see code below) and just use namespace MY. so in main program I would not have to create an object of CFoo class declared in Foo.h but I could directly access functions declared in namespace MY in Foo.h ie. void main() { MY::Open( "file.txt" ); MY::Close(); } as this is just what I need. I dont need to create an object of class CFoo which I would like to be static anyway so there is no advantage of using class as all my member I want to be static in that namespace. But if I get rid of class declaration then in the Foo.h file where the namespace is declared all variables (used inside Open() Close() function) will be global but I would like them to be hidden from user so when you type MY:: only functions Open() and Close will popup in visual studio and those should be only visiable but not other internal variables declared in same namespace MY. Now if I uncomment the CFoo class declaration then all those functions Open() etc.. CFoo class will be public and variables used by these function as private. They would be hidden from the user. This is the only reason I am trying to put this code into class otherwise I would not declare a class for it. So I tried to do this (with class declaration):
#ifndef  _FOO_H_    // we are in Foo.h file

#define	 _FOO_H_

#include <vector>
using namespace std;

typedef vector<char*> TestNames;   // Mthod 1, <--- THIS WORKS 

typedef static vector<char*> TestNames;   //Method 2, <--- THIS WAY DOESNT WORK 

______________________________________

namespace MY
{	
    class CFoo	
    {	
      public:   
            // No constructor and no destructor in this class

            static void Open();
            static void Close();          

      private:      
          TestNames names;            // ok with METHOD 1 but its not static

          static TestNames names;     // This way doesnt work with METHOD 2

};
};#endif
Is there any solution for this problem. The ideal thing would be to comment out the class declaration and just use the namspace on its own but the internal vars are public which is not what I want.:
                
#ifndef  _FOO_H_    // we are in Foo.h file

#define	 _FOO_H_

#include <vector>
using namespace std;

typedef vector<char*> TestNames;  
______________________

namespace MY
{	
     // Are all these functions and variables below static? 

     // Surely they're global. Arent they? 

     void Open();   
     void Close(); 
     
     // Variable below should be hidden but in this case its not. 

     //Its public. How can I hide it?

   
     TestNames names;     
   
};#endif
Question 2. Typedef problem again Why this doesnt compile? typedef static std::vector names; the error is: error C2159: more than one storage class specified [edited by - papa on May 31, 2004 8:05:51 AM]

Share this post


Link to post
Share on other sites
There is no way of declaring functions and or data to be private in a namespace. Also you''ve declared TestNames in global namespace and when you try to use it in MY namespace its looking in that namespace, you need to bring it into scope with "::" but i wouldn''t recommend this method, you should typedef it inside MY namespace. Is there any reason to use a vector of char pointers? for what it looks like your trying to do why not use a vector of strings? i would change it to:

#include <string>
#include <vector>

namespace MY {

typedef std::vector<std::string> name_list;

static name_list _names;

void open();
void close();
};

Share this post


Link to post
Share on other sites
thank you snk_kid.

I knew there is no way to hide those variables. So it is considered to be rather poor design putting the stuff into a namespace without a class declaration as all variables become global.

Ok. I've put all into a class but another problem arises. I dont know what that is. I've been staring at it for soo long.
When I put the implementation of Open() function in implementation file Foo.cpp then I get linkink error when I use STL map:


#ifndef _FOO_H_ // we are in Foo.h file

#define _FOO_H_

#include <vector>
#include <map>
using namespace std;

______________________________________
namespace MY{

typedef vector<string> TestNames;
typedef map<string, TestNames> TestMap;

class CFoo
{
public:
static void Open();
static void Close();
private:

static TestMap map;
static TestNames names;
};
};#endif

// we are in Foo.cpp implementation file now. THIS IS WHERE THE PROBLEM IS.
     
#include "stdafx.h"
#include "Foo.h"
using namespace MY;

void Foo::Open()
{
TestNames names;

string str = "Name_Peter";
names.push_back(str);
str = "Name_Andrew";
names.push_back(str);

string key = "key_1";
map[key] = names; //<-- IT FAILS HERE. 1 error. When I comment it then the error disappears


}



This generates error: error LNK2001: unresolved external symbol "private: static class std::map,class std::allocator >,class std::vector,class std::allocator >,class std::allocator,class std::allocator > > >,struct std::less,class std::allocator > >,class std::allocatorair,class std::allocator > const ,class std::vector,class std::allocator >,class std::allocator,class std::allocator > > > > > > TMMAP::CTexMeshMatch::Mesh_map" (?Mesh_map@CTexMeshMatch@TMMAP@@0V?$map@V?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@V?$vector@V?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@V?$allocator@V?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@@2@@2@U?$less@V?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@@2@V?$allocator@U?$pair@$$CBV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@V?$vector@V?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@V?$allocator@V?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@@2@@2@@std@@@2@@std@@A)

I just cant get rid of it. Please help!

[edited by - papa on May 31, 2004 10:11:12 AM]

Share this post


Link to post
Share on other sites
In Foo.h you forgot to include string, also nothing is really hidden, its just that the quantifier private/protected flags the compiler to throw errors and prevent code generation if someone tries to use the method/data outside of its scope. You can still have it as a module instead of user defined type, depending on the person they shouldn't need to look at the repsentation in the first place, they should be looking at the operations of a type/module

[edited by - snk_kid on May 31, 2004 10:25:59 AM]

Share this post


Link to post
Share on other sites
You need to define class members in the .cpp imp file, add:


MY::TestNames MY::CFoo::names;
MY::TestMap MY::CFoo::map;


to the begin of map.cpp you can also initialize it to a non default constructor at the same time, something like so:


MY::TestMap MY::CFoo::map = MY::TestMap();
MY::TestNames MY::CFoo::names = MY::TestNames(25); //25 names


[edited by - snk_kid on May 31, 2004 11:03:08 AM]

Share this post


Link to post
Share on other sites
Of course!! every static member must be initialized outside constructor if there is any and must be put into .cpp. Gosh I''ve been doing this so many times.

I cant believe I''ve spent so much time on this. I''m so silly.
argghhhh... Thank you ssooo much snk_kid.

Share this post


Link to post
Share on other sites
Going back to the original question, another solution is to just put TestNames names; in an un-named namespace nested in your MY namespace in the cpp file, which makes it so it won''t be linked.

In your header file:

namespace MY
{
void Open();
void Close();
}


and then in your cpp file put:

namespace MY
{
namespace
{
TestNames names; // only accessible in this translation unit

}
void Open() { /* your function definition */ }
void Close() { /* your function definition */ }
}


Still, I''d recommend using objects instead -- a singleton instead of a monostate though.

Share this post


Link to post
Share on other sites