/ Forside / Teknologi / Udvikling / C/C++ / Nyhedsindlæg
Login
Glemt dit kodeord?
Brugernavn

Kodeord


Reklame
Top 10 brugere
C/C++
#NavnPoint
BertelBra.. 2425
pmbruun 695
Master_of.. 501
jdjespers.. 500
kyllekylle 500
Bech_bb 500
scootergr.. 300
gibson 300
molokyle 287
10  strarup 270
Union med klasse-medlem
Fra : Soeren Sandmann


Dato : 15-06-01 16:31

union u {
string s;
};

afvises af g++ med beskeden:

member `class string u::s' with constructor not allowed in union

Hvad betyder det, og hvad kan jeg gøre for at komme uden om det?

"Lad være med at bruge en union, brug nedarvning i stedet" er ikke
godt nok, for der er tale om en union som bliver genereret af Bison.

 
 
Igor V. Rafienko (15-06-2001)
Kommentar
Fra : Igor V. Rafienko


Dato : 15-06-01 17:24

* Soeren Sandmann

> union u {
> string s;
> };


Du vil ikke gjøre dette (representasjonen til std::string kan
inneholde _mye_ "stæsj" som man _ikke_ vil pelle fra hverandre)


> afvises af g++ med beskeden:
>
> member `class string u::s' with constructor not allowed in union


g++ har rett.


> Hvad betyder det,


Det betyr _nøyaktig_ det kompilatoren sier:

[quote 9.5 p 1]

An object of a class with a non-tricial constructor (12.1), a
non-trivial copy constructor (12.8), a non-trivial destructor (12.4),
or a non-trivial copy assignment operator (13.5.3, 12.8) cannot be a
member of a union, nor can an array of such objects.

[/quote]


> og hvad kan jeg gøre for at komme uden om det?


Hvilket problem forsøker du å løse (hva skal string være i union
sammen med?)


> "Lad være med at bruge en union, brug nedarvning i stedet" er ikke
> godt nok, for der er tale om en union som bliver genereret af Bison.


Hva det nå enn er som genererer union av string, må det rettes på.





ivr
--
Amy: Psst... look what life was like before genetic engeneering.
Leela: Those poor 20th century women...
-- Futurama, "Why must I be a Crustacean in love?"

Soeren Sandmann (15-06-2001)
Kommentar
Fra : Soeren Sandmann


Dato : 15-06-01 17:41

> Hvilket problem forsøker du å løse (hva skal string være i union
> sammen med?)

Her er det relevante udsnit af min .y-fil:

%union {
/* her indsættes en række pointere til knuder i syntakstræet */
int bool_const;
int int_const;
char *string_const;
}

Når scanneren ser en strengkonstant, udfører den:

\"([^\"])*\" {
yylval.string_const = strdup (yytext + 1);
yylval.string_const [strlen (yytext) - 1] = '\0';
}

hvor yylval er en instans af ovenstående union. Jeg vil gerne bruge
std::string i stedet for char * hvis det kunne lade sig gøre.

> > "Lad være med at bruge en union, brug nedarvning i stedet" er ikke
> > godt nok, for der er tale om en union som bliver genereret af Bison.
>
>
> Hva det nå enn er som genererer union av string, må det rettes på.

Bison genererer kun en union med en string i fordi jeg beder den om
det - det vil jeg så lade være med. Det er ikke noget stort problem,
for indholdet af unionen bliver alligevel hurtigt konverteret til et
syntakstræ, hvor der er ikke er nogen problemer med at bruge string.

Igor V. Rafienko (15-06-2001)
Kommentar
Fra : Igor V. Rafienko


Dato : 15-06-01 18:22

* Soeren Sandmann

[snip]

> hvor yylval er en instans af ovenstående union. Jeg vil gerne bruge
> std::string i stedet for char * hvis det kunne lade sig gøre.


IMVHO kan du godt la være: hadde du brukt union av string, ville du ha
konvertert den ganske kjapt uansett (slik du beskriver selv). I og med
at yylval blir oppdatert automagisk er sjansene for obskure pekerfeil
redusert, og dersom det eneste det virkelige programmet ditt plukker
på er det konverterte treet (bygger du det mens du parserer?), så er
ikke det så veldig mye å tape (imvho) på å leve med char*s en liten
stund. (men for all del: personlig applauderer jeg ønsket om å jobbe
med strings framfor char*s).


> Bison genererer kun en union med en string i fordi jeg beder den om
> det - det vil jeg så lade være med.


Stemmer, yylval var jo en union av mulige token typer, iirc.


> Det er ikke noget stort problem, for indholdet af unionen bliver
> alligevel hurtigt konverteret til et syntakstræ, hvor der er ikke er
> nogen problemer med at bruge string.


Jeg tror[tm] dette vil være en god løsning. Hvis du bygger treet
samtidig som du parserer, så kan du kanskje bruke yytext direkte
framfor å legge noe spennende i yylval?





ivr
--
Diplomacy is the art of saying "nice doggy" until you can find a rock.

Soeren Sandmann (15-06-2001)
Kommentar
Fra : Soeren Sandmann


Dato : 15-06-01 19:20

igorr@ifi.uio.no (Igor V. Rafienko) writes:

> Jeg tror[tm] dette vil være en god løsning. Hvis du bygger treet
> samtidig som du parserer, så kan du kanskje bruke yytext direkte
> framfor å legge noe spennende i yylval?

Problemet med dét er jeg har brug for information om mere end et token
ad gangen. Der ligger også information om et tokens linjenummer og
position på linjen i yylval, så jeg kan skrive noget der ligner dette:

| T_TRY blk_statement catches
{
position_t *pos = new position_t ($1.token.line_begin, $3->line_end,
$1.token.char_begin, $3->char_end);
$$ = new try_statement_t (pos, ...);
}

På den måde har jeg præcis information om positionen (i
inputfilen) af hver syntakstræsknude.

John Mørck Hansen (20-06-2001)
Kommentar
Fra : John Mørck Hansen


Dato : 20-06-01 20:01

"Soeren Sandmann" skrev:
>
> union u {
> string s;
> };
>
> afvises af g++ med beskeden:
>
> member `class string u::s' with constructor not allowed in union
>
> Hvad betyder det, og hvad kan jeg gøre for at komme uden om det?
>
> "Lad være med at bruge en union, brug nedarvning i stedet" er ikke
> godt nok, for der er tale om en union som bliver genereret af Bison.

Uden at videt det, så tror jeg ikke du er helt afklaret, med hvad en union
er !!!
En union er en måde hvor på man kan få flere basale datatype til, at bruge
samme adresselager samtidig !!!

Det vil sige at når du ændre en værdi i en af variablerne i din union, så
ændre alle medlemmerne af din union værdi !!!

Ja, du kan sikkert forstille dig hvad der kan gå galt hvis den variabel i
klassen String som holder styr på størrelsen af klassens datalager bliver
overskrævet :\

(John =




Mogens Hansen (20-06-2001)
Kommentar
Fra : Mogens Hansen


Dato : 20-06-01 21:24


"John Mørck Hansen" <adilock@it.dk> wrote in message
news:9gqs13$glb$1@news.cybercity.dk...

> En union er en måde hvor på man kan få flere basale datatype til, at bruge
> samme adresselager samtidig !!!
>
> Det vil sige at når du ændre en værdi i en af variablerne i din union, så
> ændre alle medlemmerne af din union værdi !!!
>

Strengt taget er det ikke rigtigt at alle medlemmerne ændrer værdi.
Det medlem der bliver assignet bliver aktivt og får en veldefinet værdi.
De andre medlemmer bliver ugyldige.
Med en enkelt undtagelse, er anvendelse af de andre datamedlemmer i C99
"implementation-defined" (§6.5.2.3-5) og i C++ er det ikke defineret
opførsel (§9.5).
Det er dog ikke ualmindeligt at se programmer, der bruger unions til
konvertering.

Venlig hilsen

Mogens Hansen



Soeren Sandmann (20-06-2001)
Kommentar
Fra : Soeren Sandmann


Dato : 20-06-01 21:42

"Mogens Hansen" <mogens_h@dk-online.dk> writes:

> Med en enkelt undtagelse, er anvendelse af de andre datamedlemmer i C99
> "implementation-defined" (§6.5.2.3-5) og i C++ er det ikke defineret
> opførsel (§9.5).

Jeg troede faktisk det var udefineret, også i C. Så blev jeg lidt
mere afklaret.

Mogens Hansen (21-06-2001)
Kommentar
Fra : Mogens Hansen


Dato : 21-06-01 05:40


"Soeren Sandmann" <sandmann@daimi.au.dk> wrote in message
news:ye866dqopdl.fsf@daimi.au.dk...
> "Mogens Hansen" <mogens_h@dk-online.dk> writes:
>
> > Med en enkelt undtagelse, er anvendelse af de andre datamedlemmer i C99
> > "implementation-defined" (§6.5.2.3-5) og i C++ er det ikke defineret
> > opførsel (§9.5).
>
> Jeg troede faktisk det var udefineret, også i C. Så blev jeg lidt
> mere afklaret.

Det var udefineret før C99 (C89 ?), men der blev lavet en lille ændring.

Venlig hilsen

Mogens Hansen



John Mørck Hansen (21-06-2001)
Kommentar
Fra : John Mørck Hansen


Dato : 21-06-01 08:17

"Mogens Hansen" skrev:
>
> Strengt taget er det ikke rigtigt at alle medlemmerne ændrer værdi.
> Det medlem der bliver assignet bliver aktivt og får en veldefinet værdi.
> De andre medlemmer bliver ugyldige.
> Med en enkelt undtagelse, er anvendelse af de andre datamedlemmer i C99
> "implementation-defined" (§6.5.2.3-5) og i C++ er det ikke defineret
> opførsel (§9.5).
> Det er dog ikke ualmindeligt at se programmer, der bruger unions til
> konvertering.

Det har du fuldstændig ret i. min forklaring var bare en hurtig og nem måde
at forklare en union på.

(John =



Soeren Sandmann (20-06-2001)
Kommentar
Fra : Soeren Sandmann


Dato : 20-06-01 21:29

"John Mørck Hansen" <adilock@it.dk> writes:

> Uden at videt det, så tror jeg ikke du er helt afklaret, med hvad en union
> er !!!

Jeg er nogenlunde klar over hvad en union er i et C-program. Eftersom
jeg gjorde noget som ikke er tilladt, er jeg tydeligvis mindre klar
over hvad det er i et C++-program.

> Ja, du kan sikkert forstille dig hvad der kan gå galt hvis den variabel i
> klassen String som holder styr på størrelsen af klassens datalager bliver
> overskrævet :\

I et C-program ville det nedenstående, på nær hvad der måtte være af
slåfejl, være lovligt (men ikke særlig brugbart):

#include <stdlib.h>
#include <string.h>

typedef union U U;
typedef struct String String;

struct String {
char *data;
int alloc;
int len;
};

union U {
int y;
int x;
int z;
String s;
};

int
main ()
{
U u;
String s;

s.len = 25;
s.alloc = strlen ("noget tekst");
strcpy (s.data, "noget tekst");

u.s = s;

...


Hvis man på dette sted i programmet tildeler noget til u.y, fx

u.y = 17

og derefter forsøger at bruge u.s til noget, vil det med stor
sandsynlighed gå galt; programmet opførsel er ikke defineret.
Generelt er programmets opførsel udefineret hvis man i et C-program
tildeler noget til et medlem af en union og derefter bruger et andet
medlem af samme union.

Det som g++ brokkede sig over da jeg puttede en std::string i en
union, var at der var et union-medlem med en constructor.

Det giver god mening af compileren brokker sig, for constructorens
opgave er typisk at initialisere den hukommelse som allokeres til en
ny instans af klassen. Resten af koden i en C++-klasse vil antage at
constructoren har gjort sit arbejde, men hvis der i mellemtiden er
blevet skrevet til et af de andre medlemmer af unionen, holder denne
antagelse kun hvis compileren har allokeret separat hukommelse til
hvert medlem (og så forsvinder den eneste pointe ved unions).

Søg
Reklame
Statistik
Spørgsmål : 177552
Tips : 31968
Nyheder : 719565
Indlæg : 6408849
Brugere : 218887

Månedens bedste
Årets bedste
Sidste års bedste