Topic: Member data with function scope?
Author: Rob Stewart <stew@datalytics.com>
Date: 1996/05/21 Raw View
Matt Arnold wrote:
>
> mtm4@rsvl.unisys.com (Michael McCormick) writes:
>
> >One dark and stormy night on 16 May 1996 16:54:17 PDT, clamage@Eng.Sun.COM
> >(Steve Clamage) revealed the following:
>
> >>In article 69t@engnews1.Eng.Sun.COM, mtm4@rsvl.unisys.com (Michael McCormick)
> >writes:
> >>>I have some data that needs to persist with the object it's in, but should
> >>>only be accessed by one particular method of the class.
> >>>
> >>> - If I declare it as a class member outside the method, obviously other
> >>>methods will see it too.
> >>>
> >>> - If I declare it within the method, it must either be auto (but I would
> >>>lose the persistence) or static (I would lose the object locality).
> >>>
> >>>Surprisingly, it seems impossible in C++ to get both the scope and the
> >>>persistence that I want. Can't I have my cake and eat it too? :)
> >>>
> >>Having per-object data that is hidden from some member functions IMHO doesn't
> >>fit the C++ object model. From whom are you protecting the data?
>
> >>If a member function needs some state independent of any one object, you can
> >>give it local static data. If you find a member function needs per-object
> >>data that really should be hidden from other member functions, I would
> >>say you have not factored your design properly. You probably need
> >>another class to encapsulate some particular functionality.
>
> >Thanks for your response. If C++ does not support method scope class
> >members, then obviously I have to agree with you that they don't not
> >fit the C++ data model!
>
> Sure it does (sort of)...
>
> // below, UserClass::Func() is the one you are trying to create
[snipped code that illustrates a friend class that houses the
data that must be local to a mf with access restricted to that
mf]
That code illustrates one means of what Steve mentioned in the
first place--that protecting the information in this way
suggests that the design is flawed or not sufficient to handle
all requirements.
> >In my case, it is not really a question of protecting the data from
> >anyone. The problem is that there is a method which is called
> >iteratively and must remember per-object state information between
> >calls. In C it would be static data, but in C++ it needs to be
> >per-object in this instance.
But it wouldn't be static data in C either. If you had
functions that operated on multiple files or lists, you would
supply a handle of some sort to the functions (which is the
equivalent to the this pointer in a C++ class mf call). A
static variable in one of those functions would be no more
useful in C than it would be in C++. You would store that
variable in data accessed by the handle, where it would be
accessible by all related functions that get that handle.
This is no different than a private dm that is visible to all
mfs of a class. The handle is the this pointer, but the
variable must still be referenced by it, so all mfs can access
it.
The previous example was one means of protecting the data.
Another would be to encapsulate the functionality related to
that data in a base class, so you limit what the derived class
can do with it.
You could also have a static list object in the mf, and store
per object data in the nodes of that list. You'd locate the
data in question via the this pointer. Note, however, that you
can't destroy that data until your program ends and code
executes to destruct that static list object.
> >As a result, the language forces me to make the data into a class
> >member even though it is in fact local to that method. You may argue
> >that this isn't a problem since it is a matter of protecting myself
> >from myself. But in fact, many people can contribute code to this
> >class now and in future, so I regard the exposure of my method's local
> >state data to the sibling methods as a needless maintainability threat
> >thrust upon me by the C++ data model.
It's a problem thrust upon you by you. You have different
expectations of your C++ code than you did of your C code.
--
Robert Stewart | My opinions are usually my own.
Datalytics, Inc. | stew@datalytics.com
---
[ comp.std.c++ is moderated. To submit articles: Try just posting with your
newsreader. If that fails, use mailto:std-c++@ncar.ucar.edu
comp.std.c++ FAQ: http://reality.sgi.com/austern/std-c++/faq.html
Moderation policy: http://reality.sgi.com/austern/std-c++/policy.html
Comments? mailto:std-c++-request@ncar.ucar.edu
]
Author: willer@carolian.com (Steve Willer)
Date: 1996/05/21 Raw View
mtm4@rsvl.unisys.com (Michael McCormick) wrote:
>In my case, it is not really a question of protecting the data from
>anyone. The problem is that there is a method which is called
>iteratively and must remember per-object state information between
>calls. In C it would be static data, but in C++ it needs to be
>per-object in this instance.
Hmm...well, it may seem strange at first, but what about this for an
idea:
---- HEADER FILE ------------------------------------
struct MyClassData; // can I declare this within the MyClass scope?
class MyClass {
MyClassData *data;
public:
MyClass();
DoStuff();
}
---- MODULE FILE ------------------------------------
struct MyClassData {
int Iter;
}
MyClass::MyClass()
{
data = new MyClassData;
data->Iter = 5;
}
MyClass::~MyClass()
{
delete data;
}
MyClass::DoStuff()
{
// do stuff
if (++(data->Iter))
DoStuff();
}
Of course, I would use an auto_ptr instead of a pointer, but I didn't
want to complicate it.
>so I regard the exposure of my method's local
>state data to the sibling methods as a needless maintainability threat
>thrust upon me by the C++ data model.
I think that you're making a mistake in trying to make the C++ data
model fit your idea of class structure. Having member-specific data is
just not the way it works; the encapsulation lies at the _class_ level.
If you want to hide it from children, then you can use the method I have
above. If you want to make it inaccessible, just declare it private.
---
[ comp.std.c++ is moderated. To submit articles: Try just posting with your
newsreader. If that fails, use mailto:std-c++@ncar.ucar.edu
comp.std.c++ FAQ: http://reality.sgi.com/austern/std-c++/faq.html
Moderation policy: http://reality.sgi.com/austern/std-c++/policy.html
Comments? mailto:std-c++-request@ncar.ucar.edu
]
Author: viali@montrouge.sinet.slb.com
Date: 1996/05/28 Raw View
>>I have some data that needs to persist with the object it's in, but should only
>>be accessed by one particular method of the class.
..
>>Surprisingly, it seems impossible in C++ to get both the scope and the
>>persistence that I want. ..... If I've misunderstood the language, and it
>>actually does provide this capability ... If it doesn't ... maybe it should?
If I haven't misunderstood it (indirectly) does ;
struct test_class
{
void f();
class f_data
{
friend void test_class::f();
int a;
} private_data;
};
void test_class::f()
{
private_data.a++;
}
[ comp.std.c++ is moderated. To submit articles: try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ FAQ: http://reality.sgi.com/employees/austern_mti/std-c++/faq.html ]
[ Policy: http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu ]
Author: mtm4@rsvl.unisys.com (Michael McCormick)
Date: 1996/05/16 Raw View
I have some data that needs to persist with the object it's in, but should only
be accessed by one particular method of the class.
- If I declare it as a class member outside the method, obviously other methods
will see it too.
- If I declare it within the method, it must either be auto (but I would lose
the persistence) or static (I would lose the object locality).
Surprisingly, it seems impossible in C++ to get both the scope and the
persistence that I want. Can't I have my cake and eat it too? :)
If I've misunderstood the language, and it actually does provide this
capability, please set me straight.
If it doesn't ... maybe it should?
------------------------------------------------------------------
Mike McCormick // mtm4@rsvl.unisys.com // m.mccormick2@genie.com
------------------------------------------------------------------
Emperor of Cubicle J240-46
------------------------------------------------------------------
All views expressed are my own, not those of my employer.
------------------------------------------------------------------
While you're out surfing the internet...
I'm back on the beach blowing my little lifeguard whistle.
------------------------------------------------------------------
[ comp.std.c++ is moderated. To submit articles: try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ FAQ: http://reality.sgi.com/employees/austern_mti/std-c++/faq.html ]
[ Policy: http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu ]
Author: clamage@Eng.Sun.COM (Steve Clamage)
Date: 1996/05/16 Raw View
In article 69t@engnews1.Eng.Sun.COM, mtm4@rsvl.unisys.com (Michael McCormick) writes:
>I have some data that needs to persist with the object it's in, but should only
>be accessed by one particular method of the class.
>
> - If I declare it as a class member outside the method, obviously other methods
>will see it too.
>
> - If I declare it within the method, it must either be auto (but I would lose
>the persistence) or static (I would lose the object locality).
>
>Surprisingly, it seems impossible in C++ to get both the scope and the
>persistence that I want. Can't I have my cake and eat it too? :)
>
>If I've misunderstood the language, and it actually does provide this
>capability, please set me straight.
>
>If it doesn't ... maybe it should?
Having per-object data that is hidden from some member functions IMHO doesn't
fit the C++ object model. From whom are you protecting the data?
If a member function needs some state independent of any one object, you can
give it local static data. If you find a member function needs per-object
data that really should be hidden from other member functions, I would
say you have not factored your design properly. You probably need
another class to encapsulate some particular functionality.
---
Steve Clamage, stephen.clamage@eng.sun.com
---
[ comp.std.c++ is moderated. To submit articles: Try just posting with your
newsreader. If that fails, use mailto:std-c++@ncar.ucar.edu
comp.std.c++ FAQ: http://reality.sgi.com/austern/std-c++/faq.html
Moderation policy: http://reality.sgi.com/austern/std-c++/policy.html
Comments? mailto:std-c++-request@ncar.ucar.edu
]
Author: marnold@netcom.com (Matt Arnold)
Date: 1996/05/18 Raw View
mtm4@rsvl.unisys.com (Michael McCormick) writes:
>One dark and stormy night on 16 May 1996 16:54:17 PDT, clamage@Eng.Sun.COM
>(Steve Clamage) revealed the following:
>>In article 69t@engnews1.Eng.Sun.COM, mtm4@rsvl.unisys.com (Michael McCormick)
>writes:
>>>I have some data that needs to persist with the object it's in, but should
>>>only be accessed by one particular method of the class.
>>>
>>> - If I declare it as a class member outside the method, obviously other
>>>methods will see it too.
>>>
>>> - If I declare it within the method, it must either be auto (but I would
>>>lose the persistence) or static (I would lose the object locality).
>>>
>>>Surprisingly, it seems impossible in C++ to get both the scope and the
>>>persistence that I want. Can't I have my cake and eat it too? :)
>>>
>>>If I've misunderstood the language, and it actually does provide this
>>>capability, please set me straight.
>>>
>>>If it doesn't ... maybe it should?
>>Having per-object data that is hidden from some member functions IMHO doesn't
>>fit the C++ object model. From whom are you protecting the data?
>>If a member function needs some state independent of any one object, you can
>>give it local static data. If you find a member function needs per-object
>>data that really should be hidden from other member functions, I would
>>say you have not factored your design properly. You probably need
>>another class to encapsulate some particular functionality.
>Hi Steve,
>Thanks for your response. If C++ does not support method scope class
>members, then obviously I have to agree with you that they don't not
>fit the C++ data model!
Sure it does (sort of)...
// below, UserClass::Func() is the one you are trying to create
#include "auto_ptr.h"
class PrivateData;
class UserClass
{
public:
void Func();
void OtherFunc();
// auto_ptr ensures private data is deleted when
// each instance of UserClass dies
auto_ptr<PrivateData> pData;
};
class PrivateData
{
private:
PrivateFuncData() { }
// no one can use me but UserClass::Func()!
friend void UserClass::Func();
};
void UserClass::Func()
{
if (!pData.get())
pData = new PrivateFuncData(); // OK
// user pData
}
void UserClass::OtherFunc()
{
if (!pData.get())
pData = new PrivateFuncData(); // error!
}
>In my case, it is not really a question of protecting the data from
>anyone. The problem is that there is a method which is called
>iteratively and must remember per-object state information between
>calls. In C it would be static data, but in C++ it needs to be
>per-object in this instance.
>As a result, the language forces me to make the data into a class
>member even though it is in fact local to that method. You may argue
>that this isn't a problem since it is a matter of protecting myself
>from myself. But in fact, many people can contribute code to this
>class now and in future, so I regard the exposure of my method's local
>state data to the sibling methods as a needless maintainability threat
>thrust upon me by the C++ data model.
OK, I see your point, but with code such as the above you can at least
enforce that no one but a specific member function can ever instantiate
the per-object private data. If anyone attempts to, they get a compile
error. This should help with maintainance since no misuse of the data
class can creep into the code.
Another approach, use a "functor" (a class that behaves like a function
call)...
class MyClass;
class SpecialFunctor
{
private:
// pmy pointer for reference
void operator()(MyClass* pmy)
{
}
// private data for "function" goes here
friend class MyClass;
};
class MyClass
{
public:
void SpecialFunc()
{
Special(this); // OK
}
private:
SpecialFunctor Special; // OK
friend class SpecialFunctor;
};
MyClass my;
SpecialFunctor(&my); // error!
This would at least put the private data into a scope that close to
what you are asking for. Although SpecialFunctor is a actually a
class, you can think of it as a function with its own scope. Since
Special is a member of MyClass, its dynamic scope it actually bounded
by the lifetime of a MyClass object. Certainly, this sets up the
relationship you want, but you may not like the syntax of presence of
the SpecialFunctor class. However, I think this is the closest you
can get to a "function" with an external scope that isn't also the
global scope in C++.
Regards,
-------------------------------------------------------------------------
Matt Arnold | | ||| | |||| | | | || ||
marnold@netcom.com | | ||| | |||| | | | || ||
Boston, MA | 0 | ||| | |||| | | | || ||
617.389.7384 (h) 617.576.2760 (w) | | ||| | |||| | | | || ||
C++, MIDI, Win32/95 developer | | ||| 4 3 1 0 8 3 || ||
-------------------------------------------------------------------------
[ comp.std.c++ is moderated. To submit articles: try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ FAQ: http://reality.sgi.com/employees/austern_mti/std-c++/faq.html ]
[ Policy: http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu ]
Author: jpsa@apollo.uk.gdscorp.com (John Aldridge)
Date: 1996/05/18 Raw View
In article <4ng9po$69t@engnews1.Eng.Sun.COM>, mtm4@rsvl.unisys.com
(Michael McCormick) writes:
> I have some data that needs to persist with the object it's in, but
> should only be accessed by one particular method of the class.
How about
class P {
public:
void mayAccess ();
private:
int onlyMayAccess;
};
class S: public P {
public:
void mayNotAccess ();
};
void P::mayAccess () { onlyMayAccess++; }
void S::mayNotAccess () { onlyMayAccess++; } // Error
or,
class T {
public:
void mayNotAccess ();
void mayAccess ();
private:
class I {
private:
int onlyMayAccess;
friend void T::mayAccess ();
};
I i;
};
void T::mayAccess () { i.onlyMayAccess++; }
void T::mayNotAccess () { i.onlyMayAccess++; } // Error
Cheers,
John Aldridge
jpsa@uk.gdscorp.com
---
[ comp.std.c++ is moderated. To submit articles: try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ FAQ: http://reality.sgi.com/employees/austern_mti/std-c++/faq.html ]
[ Policy: http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu ]