Mail Archives: djgpp/2000/03/23/18:15:15
"Campbell, Rolf [SKY:1U32:EXCH]" wrote:
> Damian Yerrick wrote:
>
> > >And most of the time they are just used to force 'read-only' for
> > >public access. To start with, I think this should have been part
> > >of the C++ specification (const public: could mean that outside
> > >that class's scope it is treated as const).
> > But that would break all existing programs if you figured out a better
> > implementation of the class that didn't use that variable.
> That is true for my example about 'const public:'. But many other
> languages offer built-in method of trapping reads/writes to variables.
> Using this scheme, accessors and mutators only need to be written when
> the library changes instead of all the time. In C++ this ability is not
> 'built-in', but it is available (I've written a templatized library to do
> just this). That class acts just like any other class with a few
> exceptions. I think it is impossible to get it perfect in C++ (I can't
> cope with passing that member variable to a function by reference). But
> just about everything else works...
>
> > Data
> > hiding is one of the reasons why accessor methods exist. How hard is
> > my_string.length()
> > when string::length() is inlined to return my_string._length?
>
> Data hiding is good for backwards compatability, but you don't need
> backwards compatability until the class changes...
Here is the templatized class I call 'Event' because it catches assignments to
and from it and allows you to call user functions (actually methods of some
other class).
If anyone chooses to use this, please notify me and include me in credits.
--
(\/) Endlisnis (\/)
s257m AT unb DOT ca
Endlisnis AT HotMail DOT com
ICQ: 32959047
------------ Event.hpp ---------------
// Coptright 1999,2000 - Rolf Campbell - s257m AT unb DOT ca
// Time-stamp: "March 23, 2000 @ 5:06:33 pm"
#ifndef EVENT_H
#define EVENT_H
template <class Obj, class Holder>
class Event {
Holder* holder;
Obj val;
Obj& (Holder::*getEvent)(const Event<Obj, Holder>&);
void (Holder::*setEvent)(Event<Obj, Holder>&, const Obj&);
public:
Event(Holder* holder,
void (Holder::*set)(Event<Obj, Holder>&, const Obj&)=0,
Obj& (Holder::*get)(const Event<Obj, Holder>&)=0);
Event(Holder* holder,
Obj& (Holder::*get)(const Event<Obj, Holder>&),
void (Holder::*set)(Event<Obj, Holder>&, const Obj&)=0);
void setSet(void (Holder::*set)(Event<Obj, Holder>&, const Obj&));
void setGet(Obj& (Holder::*get)(const Event<Obj, Holder>&));
operator Obj& ();
Event<Obj, Holder>& operator ++ ();
Event<Obj, Holder>& operator ++ (int);
Event<Obj, Holder>& operator += (const Obj&);
Event<Obj, Holder>& operator -- ();
Event<Obj, Holder>& operator -- (int);
Event<Obj, Holder>& operator -= (const Obj&);
Event<Obj, Holder>& operator = (const Obj& a);
inline void set(const Obj& val);
inline Obj& get() const;
};
template <class Obj, class Holder>
Event<Obj, Holder>::operator Obj& ()
{
if(!getEvent) return get();
return (holder->*getEvent)(*this);
}
template <class Obj, class Holder>
Event<Obj, Holder>& Event<Obj, Holder>::operator ++ ()
{
return (*this) = Obj(*this)+1;
}
template <class Obj, class Holder>
Event<Obj, Holder>& Event<Obj, Holder>::operator ++ (int)
{
return (*this) = Obj(*this)+1;
}
template <class Obj, class Holder>
Event<Obj, Holder>& Event<Obj, Holder>::operator += (const Obj& rhs)
{
return (*this) = Obj(*this)+rhs;
}
template <class Obj, class Holder>
Event<Obj, Holder>& Event<Obj, Holder>::operator -- ()
{
return (*this) = Obj(*this)-1;
}
template <class Obj, class Holder>
Event<Obj, Holder>& Event<Obj, Holder>::operator -- (int)
{
return (*this) = Obj(*this)-1;
}
template <class Obj, class Holder>
Event<Obj, Holder>& Event<Obj, Holder>::operator -= (const Obj& rhs)
{
return (*this) = Obj(*this)-rhs;
}
template <class Obj, class Holder>
Event<Obj, Holder>& Event<Obj, Holder>::operator = (const Obj& a)
{
if(!setEvent) set(a);
else (holder->*setEvent)(*this, a);
return (*this);
}
template <class Obj, class Holder>
Event<Obj, Holder>::Event(Holder* holder,
Obj& (Holder::*get)(const Event<Obj, Holder>&),
void (Holder::*set)(Event<Obj, Holder>&, const
Obj&))
{
this->holder = holder;
getEvent = get;
setEvent = set;
}
template <class Obj, class Holder>
Event<Obj, Holder>::Event(Holder* holder,
void (Holder::*set)(Event<Obj, Holder>&, const
Obj&),
Obj& (Holder::*get)(const Event<Obj, Holder>&))
{
this->holder = holder;
getEvent = get;
setEvent = set;
}
template <class Obj, class Holder>
void Event<Obj, Holder>::setSet(void (Holder::*set)(Event<Obj, Holder>&, const
Obj&))
{
setEvent = set;
}
template <class Obj, class Holder>
void Event<Obj, Holder>::setGet(Obj& (Holder::*get)(const Event<Obj,
Holder>&))
{
getEvent = get;
}
template <class Obj, class Holder>
void Event<Obj, Holder>::set(const Obj& a)
{
val = a;
}
template <class Obj, class Holder>
Obj& Event<Obj, Holder>::get() const
{
return *(Obj*)&val;
}
#if 0
// ------------------------------------------------
// | Example!!
// ------------------------------------------------
class MyClass {
float get(const Event<float, MyClass>& var);
void set(Event<float, MyClass>& var, float a);
public:
Event<float, MyClass> foo;
MyClass();
};
#pragma warning (disable:4355) // disable stupid 'this' warnings in VC6
MyClass::MyClass() : foo(this, &MyClass::set, &MyClass::get)
{
}
float MyClass::get(const Event<float, MyClass>& var)
{
cout << "get\n";
return var.get();
}
void MyClass::set(Event<float, MyClass>& var, float a)
{
cout << "set\n";
var.set(a);
}
int main()
{
MyClass a;
cin >> a.foo;
cout << a.foo;
return 0;
}
#endif
#endif
- Raw text -