Message-ID: <38DA96AE.6E7234DA@unb.ca> From: Endlisnis 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> <38D26CFC DOT 16E69D47 AT americasm01 DOT nt DOT com> Content-Type: text/plain; charset=us-ascii Content-Transfer-Encoding: 7bit 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 Event { Holder* holder; Obj val; Obj& (Holder::*getEvent)(const Event&); void (Holder::*setEvent)(Event&, const Obj&); public: Event(Holder* holder, void (Holder::*set)(Event&, const Obj&)=0, Obj& (Holder::*get)(const Event&)=0); Event(Holder* holder, Obj& (Holder::*get)(const Event&), void (Holder::*set)(Event&, const Obj&)=0); void setSet(void (Holder::*set)(Event&, const Obj&)); void setGet(Obj& (Holder::*get)(const Event&)); operator Obj& (); Event& operator ++ (); Event& operator ++ (int); Event& operator += (const Obj&); Event& operator -- (); Event& operator -- (int); Event& operator -= (const Obj&); Event& operator = (const Obj& a); inline void set(const Obj& val); inline Obj& get() const; }; template Event::operator Obj& () { if(!getEvent) return get(); return (holder->*getEvent)(*this); } template Event& Event::operator ++ () { return (*this) = Obj(*this)+1; } template Event& Event::operator ++ (int) { return (*this) = Obj(*this)+1; } template Event& Event::operator += (const Obj& rhs) { return (*this) = Obj(*this)+rhs; } template Event& Event::operator -- () { return (*this) = Obj(*this)-1; } template Event& Event::operator -- (int) { return (*this) = Obj(*this)-1; } template Event& Event::operator -= (const Obj& rhs) { return (*this) = Obj(*this)-rhs; } template Event& Event::operator = (const Obj& a) { if(!setEvent) set(a); else (holder->*setEvent)(*this, a); return (*this); } template Event::Event(Holder* holder, Obj& (Holder::*get)(const Event&), void (Holder::*set)(Event&, const Obj&)) { this->holder = holder; getEvent = get; setEvent = set; } template Event::Event(Holder* holder, void (Holder::*set)(Event&, const Obj&), Obj& (Holder::*get)(const Event&)) { this->holder = holder; getEvent = get; setEvent = set; } template void Event::setSet(void (Holder::*set)(Event&, const Obj&)) { setEvent = set; } template void Event::setGet(Obj& (Holder::*get)(const Event&)) { getEvent = get; } template void Event::set(const Obj& a) { val = a; } template Obj& Event::get() const { return *(Obj*)&val; } #if 0 // ------------------------------------------------ // | Example!! // ------------------------------------------------ class MyClass { float get(const Event& var); void set(Event& var, float a); public: Event 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& var) { cout << "get\n"; return var.get(); } void MyClass::set(Event& var, float a) { cout << "set\n"; var.set(a); } int main() { MyClass a; cin >> a.foo; cout << a.foo; return 0; } #endif #endif