Go Premium for a chance to win a PS4. Enter to Win

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 280
  • Last Modified:

static member

I am new in OO. I need to know how can I declare a class which can be accessed by all other classes and keep only one copy of the attribuites (i.e. everyone sees the same value of a attributes). I am trying to get rid of the global variable as we normally used in C.

Any help will be very much appreciated.
0
tangkh
Asked:
tangkh
  • 16
  • 12
  • 2
  • +5
1 Solution
 
nietodCommented:
The global variable is not gone.  This might be a good case for using it.  Can you provide a bit more detail about what you are trying to do?

Note that a static member of a class, acts like a global varaible, but it is accessable only to member functions and friends of the class.  It is not accessable to all classes.
0
 
mlevCommented:
Unless it's public, of course
0
 
tangkhAuthor Commented:
In fact my old programme was using global struct. Now I am trying to include "methods" within a class to modify the attribute, such as

//old
struct Ident
{
   BYTE value;
}

//new
class Ident
{
   BYTE value;
public:
   ModifyValue();
}

global variables are messive to me :(

0
Concerto Cloud for Software Providers & ISVs

Can Concerto Cloud Services help you focus on evolving your application offerings, while delivering the best cloud experience to your customers? From DevOps to revenue models and customer support, the answer is yes!

Learn how Concerto can help you.

 
mlevCommented:
Well, it seems you can do either
----------
class Ident
{
  BYTE Value;
public:
  ModifyValue();
} GlobalIdent;
.
GlobalIdent.ModifyValue();
----------
or
----------
class Ident
{
  static BYTE value;
public:
  static ModifyValue();
};
.
Ident::ModifyValue();

And don't forget to define "BYTE Ident::value;" somewhere.
-----------
0
 
nietodCommented:
tangkh, you haven't given us enough details for us to be able to say for sure what you should do.

In you above description it doesn't sound like the "attribute" needs to be acccessible from all classes.  Does it?  If not, I would use a static member, sort of like mlev's second example.  
0
 
tangkhAuthor Commented:
I have many classes with many instances, I want some of these classes to be able to access other classes' attributes. The second example by mlev seems suitable.

Is "Ident::ModifyValue()" callable from everywhere?

"And don't forget to define "BYTE Ident::value;" somewhere" <-- Where should I define this value?
0
 
nietodCommented:
>> Is "Ident::ModifyValue()" callable from everywhere?
Yes.

>> "And don't forget to define "BYTE Ident::value;" somewhere"
>> <-- Where should I define this value?

every static data variable must be defined, that is, given an initial value, one time in a program.   Thus must be a global scope (not inside a fuction or class), but It doesn't matter where other than that.  That is, it could be in any file at any location.

Thus you might have a .h file that has

class Ident
 {
    static BYTE value;
  public:
     static ModifyValue();
 };

Then somewhere you must have a file that contains the line
BYTE Ident::value = 0;

This line must ocur only one time in the whole project.  Thus it ussualy can't be placed in the .H file.  Thus it is ussually placed in a .cpp file.
0
 
yonatCommented:
The two options to do this (both mentioned in the discussion above) are called Singleton and Monostate. You can find more about Singleton int the book "Design Patterns" and at:
* http://rampages.onramp.net/~huston/singleton.html
* http://www.eli.sdsu.edu/courses/spring98/cs635/notes/singleton/singleton.html
* http://www.object-arts.com/EducationCentre/Patterns/Singleton.htm

You can find more about Monostate in an article by Steve Ball and John Crawford in the May 97 issue of the C++ report. Basically, it is a class where all members (both data and function) are static.

There is a comparison of the two patterns at:
* http://ww2.altavista.digital.com/cgi-bin/news?msg@38060@comp%2eobject
0
 
newexpertCommented:
Just trying to be helpful here.  Some of the following has already been mentioned by above people.

Firstly, C++ class and C/C++ struct are similar.  Members of struct are public by default, while members of class are private by default.

Therefore
struct Ident { BYTE value; };
and
class Ident { public: BYTE value; };
are equivalent.

Secondly

You are still thinking in terms of having global accessible by all functions/procedures.  I assume that's why you asked to have attrib of a class (rep state of the program) be accessible by all other classes.  If you really want to do that you might as well declare a global struct

struct state_of_program { time elapsed; date started; bool stillok; /* ... */ } the_state_of_program;

and have every function to set/reset values in that structure.

In OO ways you design a class instead.  The difference is your class should take care of itself.  Error conditions are set/cleared internally.  This is possible because you've designed all the interfaces to your program.  Your program only need to report to the outside world what services(methods) are currently available.  Other functions should only need to check your program's status.

for example

class program
 {
  class err {};
  bool ok;
public:
  program() : ok(true) {}
  int isprogramok() { return ok; }
  int crashprogram() { /* mess things up here */ ok = false; }
  int resetprogram() { /* clean up mess */ ok = true; }
  int readfromprogram() { if (!ok) throw err; /* codes here */ }
 };

Now in
function()
 {
  program a;
  if (a.isprogramok()) a.crashprogram();
  try { a.readfromprogram(); }
  catch (program::err)
   {
    cerr<<"Can't do it right now.";
    a.resetprogram(); /* hopefully will correct the error. */
    try /*again*/ { a.readfromprogram(); }
    catch (program::err) { cerr << "It's hopeless!"; }
   }
 }

Notice function() do not set any attrib of program directly but still can do something about the error (for example resetprogram() or some less drastic measures if class program provides them).

Static members are not usually needed.
0
 
nietodCommented:
>> Static members are not usually needed
Not in many cases, but in this case they are.  Either a static member or a singleton is needed.
0
 
tangkhAuthor Commented:
See, the problem is, I need to have a class whose attributes can be accessed direcltly by some other classes, and can only be accessed via its functions by certain other classes. Am I demanding something beyond OO's features?
0
 
nietodCommented:
>> can only be accessed via its functions by certain other classes

The access functions can be declared private or protected and these classes that can call these functions can be declared as friends.

If the classes that will call these function are all derived from each other there is another way that might be better.  The previous comment assumed that the classes were not related.
0
 
tangkhAuthor Commented:
>>If the classes that will call these function are all derived from each other there is another way that might be better.  The previous comment assumed that the classes were not related.

Yes, this "another way" is exactly what I want. Can you tell me how to do it?
0
 
nietodCommented:
Possibly, what you want.

You can declare a protected class inside the base class.  Then the derived classes can access this class, but classes not derived from this base class cannot, for example.

class Base
{
protected:
    class PrivateData
    {
      int SomeInt;
     void SetSomeInt(int i) {SomeInt = i;};
     int GetSomeInt() { return SomeInt; };
    };

    static PrivateData PD;
};

class Derived : public Base
{
  void SomeFunction ()
  {
      int i = PD.GetSomeInt();
  }
};


0
 
newexpertCommented:
tangkh:

Have you ever heard of friend function or friend class?

friend function is an independent function that has access to private members of a class, provided it is listed as friend of that class:

for example

class a
 {
  int privateattrib;
public:
  friend int independent(); // list all friends
 };

int independent()
 {
  a.privateattrib = 1;
  return a.privateattrib++;  
 }

Similarly you can have a friend class.

class a
 {
  int privateattrib;
public:
  int& access() { return privateattrib; } // access function
  friend class b; // b is a friend.
 };

class b
 {
public:
  int dosomething()
   {
    a anobject;
    anobject.privateattrib = 0; // direct access.
    return anobject.privateattrib++; // direct access.
   }
 };

class c
 {
public:
  int dosomething()
   {
    a anobject;
    anobject.access() = 0; // access via access function.
    return anobject.access()++; // access via access function.
   }
 };

The point being, in OO who has access to private member of class a is strictly controlled by a.  This is not the case with global variable.

I hope this answers your question.
0
 
Booth882Commented:
newexpert is right, friend classes are what you need. all the classes you want to have access to the privates of this single class you declare as a friend class in the public section of the single class, like:

class This
{
public:
    friend class Other;
    friend class Neither;

this way the Other and Neither classes have access to the This class, while all unmentioned classes do not.



0
 
nietodCommented:
Friend classes were already suggested on August 10 11:06.

Then he asked for the private class solution.  Possibly because the proavate class solution allows the class hierarchy to be expanded without changes to the base class.
0
 
tangkhAuthor Commented:
I tried the following, but couldn't work:

class a  //non-MFC
{
public:
  CStatic m_B;  //MFC of the radio button
  static doSomething();
};

a::dosomething()
{
  m_B.ShowWindow(Enable);
}

class c
{
public:
  doAnother();
};

c::doAnother()
{
  a::doSomething();
}

What is wrong??
0
 
nietodCommented:
well first of all, is "c" supposed to be derived from "a"?
0
 
tangkhAuthor Commented:
No. "c" is a non-MFC, independent on "a", which is a MFC (I am sorry I made a mistake, a should be a MFC).
0
 
nietodCommented:
What is the problem you are getting?  are you getting compiler errors?  which ones.  Are you getting run-time errors?  what and where?
0
 
tangkhAuthor Commented:
I got the run time error when accessing m_B.ShowWindow() function  from class c.
0
 
nietodCommented:
I don't know MFC, but I blieve an MFC window object needs to be attached to a window in some way.  (by opening a window or attaching to an existing window.)  If the m_b object is not attached to a window, you might get an error.  Could that be the problem?
0
 
krishnakumarCommented:
I think the code is wrong ( It should have given compiler error).
You can not directly access a non static member from a static member function. You need a object to access the nonstatic member.
In your code make m_B as static.
And Are you calling CStatic::create(...) function with valid window object ?


0
 
nietodCommented:
Yupp. I missed that.  I think I saw the "CStatic" and read it as "static"
0
 
tangkhAuthor Commented:
Oh yes, I missed that too. It should be static CStatic m_B;
0
 
nietodCommented:
So it was wrong here, but not in the actual code?

If so, did you attach m_B to a window?  Either by opening a window or by using attach()?
0
 
tangkhAuthor Commented:
Sorry again :) I mean I have added "static" in my source. The m_B is a MFC button Class.
0
 
nietodCommented:
Is the button class attached to a real window?  That is, did you open a window for this button or did you attach it to a window with the attach() function.

I don't use MFC, but to the best of my knowledge you cannot call ShowWindow() on an MFC window object unless that window object is attached to a "real" window.
0
 
tangkhAuthor Commented:
Oh, yes, m_B is created by using Visual C++ 's button class.
0
 
nietodCommented:
You don't understand.  

a button is a type of window.
an MFC button object is a type window object, that is it is derived from CWnd.
an MFC window object (button or otherwise) is used to manage a window (button or otherwise).
To do this, the MFC window object needs to be attached to the window it will be "managing"
This is ussually done by opening a new window with the Create() or CreateEx() procedures.  Or it may be done by attaching the window object to an existing window using the attach() procedure.

The followign is taking from the MFC documents.

Relationship Between a C++ Window Object and an HWND

Home | Overview | How Do I | Tutorial



The window object is an object of the C++ CWnd class (or a derived class) that your program creates directly. It comes and goes in response to your program's constructor and destructor calls. The Windows window, on the other hand, is an opaque handle to an internal Windows data structure that corresponds to a window and consumes system resources when present. A Windows window is identified by a "window handle" (HWND) and is created after the CWnd object is created by a call to the Create member function of class CWnd. The window may be destroyed either by a program call or by a user's action. The window handle is stored in the window object's m_hWnd member variable. The following figure shows the relationship between the C++ window object and the Windows window. Creating windows is discussed in Creating Windows. Destroying windows is discussed in Destroying Window Objects.

Window Object and Windows Window



0
 
Answers2000Commented:
The neatest way is the singleton pattern.  [i put the code inline in the class to save space, but you may want to re-arrange the layout]

in .h

class MyClass
{
private:
   static MyClass m_This ;  // only one copy of this object
   MyClass() { ; } // nobody can create this object except this class

public:
   virtual ~MyClass() { ; } // destructor, whatever you need here
   MyClass& Get() { return *this ; } // allow other people to get access to this object

   // You data or functions go here, e.g
   int m_myinteger ;
   void somefunction() { ; }
} ;


in only one .cpp
static MyClass MyClass::m_This ;

rest of code then can access this class by doing stuff like
MyClass::Get().somefunction() ;
MyClass::Get().m_myinteger = 99 ;




0
 
krishnakumarCommented:
nietod is right. As I mentioned earlier the create() function of CStatic class takes parent window reference(Forth parameter). Make sure that your are calling this function with not passing NULL to this parameter. And you should call this function after instantiating this class.
0
 
nietodCommented:
answers2000, did you read the question history?
0
 
tangkhAuthor Commented:
In fact many of you have answered my question. How can I reward you guy at once?
0
 
nietodCommented:
Unfortunately, there is no way to split points among experts.  You must choose the expert you think was most helpful and ask them to answer.  (If they don't have the current pending answer.)  If you really feel that more than one expert deserves the points, and if you have the points, then you can ask a "dummy" question (or several) for another (or several) experts to answer.  (Place the expert's name in the question.)  However, you are not obligated to do so.
0
 
tangkhAuthor Commented:
So bsides "thanks", I cant really do anything?
0

Featured Post

How to Use the Help Bell

Need to boost the visibility of your question for solutions? Use the Experts Exchange Help Bell to confirm priority levels and contact subject-matter experts for question attention.  Check out this how-to article for more information.

  • 16
  • 12
  • 2
  • +5
Tackle projects and never again get stuck behind a technical roadblock.
Join Now