|
| Mærkelig opbygning af struct Fra : Jonas Nielsen |
Dato : 14-06-02 23:45 |
|
Jeg arbejder med en netværkssimulator der hedder ns.
Når man skal simulere en pakke foregår det på en måde jeg ikke før har
set i c++.
Selve pakke-struct'en (kaldet srh) består af en række variable f.eks.
int route_reply_len_;
og en tilhørende funktion f.eks.
inline int& route_reply_len() { return route_reply_len_; }
Når man nu skal sætte variablen fra en anden klasse gøres det således:
srh->route_reply_len() = len;
Hvis man skal hente variablen fra en anden klasse gøres det således:
len = srh->route_reply_len();
Er der nogen har en ide om hvad fordelen kan være ved at programmere
på denne måde ?
| |
Thomas Lykkeberg (15-06-2002)
| Kommentar Fra : Thomas Lykkeberg |
Dato : 15-06-02 07:31 |
|
On 15 Jun 2002 00:45:25 +0200, Jonas Nielsen <jonasn@diku.dk> wrote:
>
>Jeg arbejder med en netværkssimulator der hedder ns.
>
>Når man skal simulere en pakke foregår det på en måde jeg ikke før har
>set i c++.
>
>Selve pakke-struct'en (kaldet srh) består af en række variable f.eks.
>
> int route_reply_len_;
>
>og en tilhørende funktion f.eks.
>
> inline int& route_reply_len() { return route_reply_len_; }
>
>Når man nu skal sætte variablen fra en anden klasse gøres det således:
>
> srh->route_reply_len() = len;
>
>Hvis man skal hente variablen fra en anden klasse gøres det således:
>
> len = srh->route_reply_len();
>
>Er der nogen har en ide om hvad fordelen kan være ved at programmere
>på denne måde ?
Kig på erklæringen af funktionen route_reply_len(). Den returnerer en
"reference" til medlems variablen route_reply_len_, hvilket betyder at
de to eksempler du viste faktisk bliver noget i stil med:
srh->route_reply_len() = len;
*(&route_reply_len_) = len;
len = srh->route_reply_len();
len = *(&route_reply_len_);
Dette er nu meget normalt i C++, se foreksempel på cin og cout, her
kan man gøre det samme.
Fordelen er at du ikke behøver at lave 2 funktioner, nemlig en til
"set" og en til "read". Denne gør det i et hug.
/Thomas
| |
Mogens Hansen (15-06-2002)
| Kommentar Fra : Mogens Hansen |
Dato : 15-06-02 21:39 |
|
"Thomas Lykkeberg" <thomasDOTlykkeberg@privatDOTdk> wrote
> Dette er nu meget normalt i C++, se foreksempel på cin og cout, her
> kan man gøre det samme.
>
Jeg finder det atypisk.
Hvilke funktioner tænker du præcist på ?
Jeg mener hvor i forbindelse med klasserne
ios_base
basic_ios
basic_istream
basic_ostream
finder du et totalt brud på indkapsling (ved at give en non-const reference
til private data), og et brud på const-korrektheden så man ikke kan læse
information, der ikke ændrer på objektet ?
> Fordelen er at du ikke behøver at lave 2 funktioner, nemlig en til
> "set" og en til "read". Denne gør det i et hug.
Er den lille fordel et godt kompromis, set i forhold til ulemperne, prisen
værd ?
Principielt er det ikke synd for biblioteksforfattere at de skal skrive lidt
ekstra, hvis biblioteket til gengæld bliver lettere og/eller sikrere at
bruge.
Dels er biblioteksforfattere (typisk) i mindretal.
Dels skal det være nemmere at bruge et bibliotek end at skrive det.
Venlig hilsen
Mogens Hansen
| |
Mogens Hansen (15-06-2002)
| Kommentar Fra : Mogens Hansen |
Dato : 15-06-02 21:39 |
|
"Jonas Nielsen" <jonasn@diku.dk> wrote
> Er der nogen har en ide om hvad fordelen kan være ved at programmere
> på denne måde ?
Fordel i forhold til hvilke andre design og hvilke vurderings kriterier ?
Nogle relevante vurderings kriterier kunne være:
* Performance (forventet med en bare nogenlunde compiler)
* Indkapsling
* const korrekthed
* Syntaks for brugeren
* Mulighed for fejlagtigt brug
* Initialisering
* Invarians
Nogle relevante alternative design kunne være (ingen er compileret):
Original:
Performance: Optimal
Indkapsling: Ingen! (Det ser bare sådan ud)
const korrekthed: Nej. "route_reply_len" kan ikke læses med et const
object.
Syntaks: Lidt atypisk
Initialisering: Ikke vist i eksemplet
Invarians: Ikke vist i eksemplet
Alternative 1:
En åben struktur:
struct srh
{
int route_reply_len;
};
Performance: Optimal
Indkapsling: Ingen
const korrekthed: Ja
Syntaks: Simplest
Initialisering: overladt til brugerens diciplin
Invarians: etableres ikke ved oprettelse, og checkes ikke senere
Alternativ 2:
En klasse med tilgangsmetoder:
class srh
{
public:
int route_reply_len() const
{ return route_reply_len_; }
void route_reply_len(int len)
{ route_reply_len_ = len; }
private:
int route_reply_len_;
};
Performance: Optimal
Indkapsling: Ja
const korrekthed: Ja
Syntaks: traditionel
Initialisering: ikke påkrævet
Initialisering: overladt til brugerens diciplin
Invarians: etableres ikke ved oprettelse, og checkes ikke senere
Alternativ 3:
En klasse, der initialiseres i konstructor og hvor datamedlemmer kan læses
men ikke sættes
class srh
{
public:
srh(int route_reply_len) :
route_reply_len_(len) {}
int route_reply_len() const
{ return route_reply_len_; }
private:
int route_reply_len_;
};
Performance: Optimal
Indkapsling: Ja
const korrekthed: Ja
Syntaks: traditionel
Initialisering: Ja
Invarians: Kan testes i constructor, og kan ikke senere brydes
Kort sagt syntes jeg der er andre design muligheder, der er bedre end det
originale.
Venlig hilsen
Mogens Hansen
| |
|
|