chip@ateng.UUCP (Chip Salzenberg) (03/29/88)
Several people have griped because they cannot provide access to member
variables and also have the compiler automatically call a user-written
routine when the value is modified.
Actually, it's quite easy. Don't return a "foo&", just create a class
whose only purpose in life is to be a "foo imposter". Here is an example
that demonstrates the technique. (Be warned, I haven't compiled this; but I
have used the technique before.)
================ BEGIN EXAMPLE ==================
// temp conversion routines
extern float ftoc(float); // F --> C
extern float ctof(float); // C --> F
// A general (F/C) temperature.
class CelsiusImp;
class FahrImp;
class Temp {
float celsius; // None of this Imperial junk :-)
public:
Temp() { celsius = 0.0; }
CelsiusImp celsius(); // See below
FahrImp fahr(); // See below
};
// A Celsius "view" of a general temperature
class CelsiusImp {
Temp* temp;
public:
CelsiusImp(Temp* t) { temp = t; }
// The magic:
operator float () { return temp->celsius; }
float operator = (float f) { return (temp->celsius = f); }
};
// A Fahrenheight "view" of a general temperature
class FahrImp {
Temp* temp;
public:
FahrImp(Temp* t) { temp = t; }
// The magic:
operator float () { return ctof(t->celsius); }
float operator = (float f) { return (t->celsius = ftoc(f)); }
};
// Circular class references force me to put these functions last.
CelsiusImp Temp::celsius() { return CelsiusImp(this); }
FahrImp Temp::fahr() { return FahrImp(this); }
================ END EXAMPLE ==================
So there you have it: now you can write
Temp t;
t.fahr() = 212; // call FahrInp::operator=()
cout << "Water boils at " << t.celsius() << "degrees C\n";
and you can put whatever code you want into the operator=() functions.
Now stop complaining and write those programs. :-)
--
Chip Salzenberg "chip@ateng.UU.NET" or "codas!ateng!chip"
A T Engineering My employer's opinions are a trade secret.
"Anything that works is better than anything that doesn't."