S
HumeSikkins schrieb:
...
Ein schönes Beispiel von Jim Hyslop:
class animal {
protected:
point3d whereAmI;
// ... etc.
};
class fish : public animal {
// whatever
};
class bird : public animal {
public:
// birds of a feather...
void flockTogether(animal &a) const { a.whereAmI = whereAmI; }
};
int main() {
fish f;
bird b;
b.flockTogether(f); // Oops, the bird just drowned.
}
(der Kommentar ist wohl falsch: Der Vogel ist nicht ertrunken, sondern der Fisch fliegt)
Erst dachte ich: Hmmm, aber das Beispiel finde ich unbefriedigend - das sieht mehr eher nach einem "const-"-Thema aus als nach "access specification". Wenn flockTogether() einen non-const-Parameter bekommt, kann es den natürlich ändern ... ist doch irgendwie nichts Besonderes.
... aber mit ein wenig Nachdenken ist es schon klar: Wenn ich protected-Elemente habe, gehe ich davon aus, dass "ich" die ändern kann ... nicht aber, "Geschwister, Onkels und Cousins".
Anders gesagt: Wenn das anders wäre, würde folgender Hack mit Standardmittel funktioneren:
Guter Programmierer:
class base
{
protected:
int val;
};
class derived : public base
{
public:
derived(int i) { val = i;}
// legt val "NICHT nach außen"
};
Böser Programmierer:
template <typename BaseT, typename DerivedT, typename VarType>
class hack : public BaseT {
public:
typedef VarType DerivedT::*dMember;
static VarType& get(DerivedT& d, dMember dMem) {
return d.*dMem;
}
};
int main(void)
{
derived d(2);
hack<base, derived, int>::get(d, &derived::val) += 3;
// Verändert d.val, obwohl nur derived-Objekte das sollten
// (hat sich der derived-Entwickler eben so ausgedacht)
}
Danke,
Simon2.