delorie.com/archives/browse.cgi   search  
Mail Archives: djgpp/2000/03/23/18:15:15

Message-ID: <38DA96AE.6E7234DA@unb.ca>
From: Endlisnis <s257m AT unb DOT ca>
X-Mailer: Mozilla 4.7 [en] (Win98; U)
X-Accept-Language: en
MIME-Version: 1.0
Newsgroups: comp.os.msdos.djgpp,comp.lang.c++
Subject: Re: Accessor methods are annoying. (Was: Re: TABLE OF POINTERS TO
FUNCTIONS + OTHER)
References: <8am435$j8i$1 AT tron DOT sci DOT fi> <38D1079A DOT 45700792 AT americasm01 DOT nt DOT com> <l4t2dsg398i4e02b147mv18i89a5tvo0nq AT 4ax DOT com> <38D26CFC DOT 16E69D47 AT americasm01 DOT nt DOT com>
Lines: 218
Date: Thu, 23 Mar 2000 22:12:05 GMT
NNTP-Posting-Host: 24.114.6.233
X-Complaints-To: abuse AT home DOT net
X-Trace: news1.rdc1.on.wave.home.com 953849525 24.114.6.233 (Thu, 23 Mar 2000 14:12:05 PST)
NNTP-Posting-Date: Thu, 23 Mar 2000 14:12:05 PST
Organization: @Home Network Canada
To: djgpp AT delorie DOT com
DJ-Gateway: from newsgroup comp.os.msdos.djgpp
Reply-To: djgpp AT delorie DOT com

"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 -


  webmaster     delorie software   privacy  
  Copyright 2019   by DJ Delorie     Updated Jul 2019