Solved

static member

Posted on 1998-08-07
37
220 Views
Last Modified: 2010-04-10
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
Comment
Question by:tangkh
  • 16
  • 12
  • 2
  • +5
37 Comments
 
LVL 22

Expert Comment

by:nietod
ID: 1169621
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
 
LVL 2

Expert Comment

by:mlev
ID: 1169622
Unless it's public, of course
0
 

Author Comment

by:tangkh
ID: 1169623
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
 
LVL 2

Expert Comment

by:mlev
ID: 1169624
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
 
LVL 22

Expert Comment

by:nietod
ID: 1169625
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
 

Author Comment

by:tangkh
ID: 1169626
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
 
LVL 22

Expert Comment

by:nietod
ID: 1169627
>> 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
 
LVL 5

Expert Comment

by:yonat
ID: 1169628
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
 
LVL 1

Expert Comment

by:newexpert
ID: 1169629
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
 
LVL 22

Expert Comment

by:nietod
ID: 1169630
>> 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
 

Author Comment

by:tangkh
ID: 1169631
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
 
LVL 22

Expert Comment

by:nietod
ID: 1169632
>> 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
 

Author Comment

by:tangkh
ID: 1169633
>>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
 
LVL 22

Expert Comment

by:nietod
ID: 1169634
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
 
LVL 1

Expert Comment

by:newexpert
ID: 1169635
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
 
LVL 1

Expert Comment

by:Booth882
ID: 1169636
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
 
LVL 22

Expert Comment

by:nietod
ID: 1169637
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
 

Author Comment

by:tangkh
ID: 1169638
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
How to run any project with ease

Manage projects of all sizes how you want. Great for personal to-do lists, project milestones, team priorities and launch plans.
- Combine task lists, docs, spreadsheets, and chat in one
- View and edit from mobile/offline
- Cut down on emails

 
LVL 22

Expert Comment

by:nietod
ID: 1169639
well first of all, is "c" supposed to be derived from "a"?
0
 

Author Comment

by:tangkh
ID: 1169640
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
 
LVL 22

Expert Comment

by:nietod
ID: 1169641
What is the problem you are getting?  are you getting compiler errors?  which ones.  Are you getting run-time errors?  what and where?
0
 

Author Comment

by:tangkh
ID: 1169642
I got the run time error when accessing m_B.ShowWindow() function  from class c.
0
 
LVL 22

Expert Comment

by:nietod
ID: 1169643
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
 

Expert Comment

by:krishnakumar
ID: 1169644
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
 
LVL 22

Expert Comment

by:nietod
ID: 1169645
Yupp. I missed that.  I think I saw the "CStatic" and read it as "static"
0
 

Author Comment

by:tangkh
ID: 1169646
Oh yes, I missed that too. It should be static CStatic m_B;
0
 
LVL 22

Expert Comment

by:nietod
ID: 1169647
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
 

Author Comment

by:tangkh
ID: 1169648
Sorry again :) I mean I have added "static" in my source. The m_B is a MFC button Class.
0
 
LVL 22

Expert Comment

by:nietod
ID: 1169649
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
 

Author Comment

by:tangkh
ID: 1169650
Oh, yes, m_B is created by using Visual C++ 's button class.
0
 
LVL 22

Expert Comment

by:nietod
ID: 1169651
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
 
LVL 8

Accepted Solution

by:
Answers2000 earned 20 total points
ID: 1169652
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
 

Expert Comment

by:krishnakumar
ID: 1169653
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
 
LVL 22

Expert Comment

by:nietod
ID: 1169654
answers2000, did you read the question history?
0
 

Author Comment

by:tangkh
ID: 1169655
In fact many of you have answered my question. How can I reward you guy at once?
0
 
LVL 22

Expert Comment

by:nietod
ID: 1169656
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
 

Author Comment

by:tangkh
ID: 1169657
So bsides "thanks", I cant really do anything?
0

Featured Post

How to improve team productivity

Quip adds documents, spreadsheets, and tasklists to your Slack experience
- Elevate ideas to Quip docs
- Share Quip docs in Slack
- Get notified of changes to your docs
- Available on iOS/Android/Desktop/Web
- Online/Offline

Join & Write a Comment

Suggested Solutions

When writing generic code, using template meta-programming techniques, it is sometimes useful to know if a type is convertible to another type. A good example of when this might be is if you are writing diagnostic instrumentation for code to generat…
Introduction This article is the first in a series of articles about the C/C++ Visual Studio Express debugger.  It provides a quick start guide in using the debugger. Part 2 focuses on additional topics in breakpoints.  Lastly, Part 3 focuses on th…
The viewer will learn how to pass data into a function in C++. This is one step further in using functions. Instead of only printing text onto the console, the function will be able to perform calculations with argumentents given by the user.
The viewer will learn how to user default arguments when defining functions. This method of defining functions will be contrasted with the non-default-argument of defining functions.

705 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

20 Experts available now in Live!

Get 1:1 Help Now