erklære frem pekere-til-structs i C ++

stemmer
3

Jeg bruker en tredje part bibliotek som har en erklæring som dette:

typedef struct {} __INTERNAL_DATA, *HandleType;

Og jeg ønsker å lage en klasse som tar en HandleType i konstruktøren:

class Foo
{
    Foo(HandleType h);
}

uten herunder overskriften som definerer HandleType . Normalt ville jeg bare fremtids erklære en slik type, men jeg kan ikke finne ut syntaksen for dette. Jeg har veldig lyst til å si noe sånt som:

struct *HandleType;

Men som sier Forventet identifikator før * i GCC. Den eneste løsningen jeg kan se er å skrive min klasse som dette:

struct __INTERNAL_DATA;
class Foo
{
    Foo(__INTERNAL_DATA *h);
}

Men dette er avhengig av interne detaljer om biblioteket. Det vil si, det bruker navnet __INTERNAL_DATA, som er en implementering detalj.

Det virker som det skal være mulig å videresende-erklære HandleType (del av den offentlige API) uten å bruke __INTERNAL_DATA (del av gjennomføringen av biblioteket.) Noen som vet hvordan?

EDIT: Lagt til flere detaljer om hva jeg leter etter.

Publisert på 10/03/2009 klokken 19:42
kilden bruker
På andre språk...                            


5 svar

stemmer
4

Oppdater:

Jeg bruker det i gjennomføringen CPP av Foo, men jeg ønsker å unngå å inkludere det i min header .h for Foo. Kanskje jeg bare er altfor pedantisk? :)

Ja du er :) Gå videre med frem erklæringen.

Hvis HandleType er en del av grensesnittet må det være en overskrift erklære det. Bruk den spissen.

Ditt problem er fortsatt en vag en. Du prøver å beskytte mot noe du ikke kan.

Du kan legge til følgende linje i din klient bibliotek:

typedef struct INTERNAL_DATA *HandleType;

men, hvis navn / struktur endringer du kan være i for noen casting nastiness.

Prøv maler:

template <class T>
class Foo
{
    Foo(T h);
};

Forward erklæringen er fine. Hvis du skal bruke pekere eller referanser du trenger bare en klasse ( __INTERNAL_DATA) erklæring i omfang. Men hvis du skal bruke et medlem funksjon eller et objekt må du inkludere spissen.

Svarte 10/03/2009 kl. 19:46
kilden bruker

stemmer
1

Hvis du virkelig, virkelig, virkelig ønsker ikke å utsette _INTERNAL_DATA til den som ringer så din eneste reelle valget er å bruke typedef tomrommet * HandleType ; Så inni biblioteket kan du gjøre hva du vil, inkludert å endre hele gjennomføringen av * HandleType.

Bare lage en hjelper funksjon for å få tilgang til deg reelle data.

inline _INTERNAL_DATA* Impl(HandleType h) {
    return static_cast<_INTERNAL_DATA*>(h);
}
Svarte 10/03/2009 kl. 20:20
kilden bruker

stemmer
1

Jeg er ikke helt sikker på hva du går for, men følgende vil fungere uten å inkludere selve header filen:

// foo.h
class Foo
{
    public:
    template<typename T>Foo(T* h) { /* body of constructor */ }
};

Mind du, vil du fortsatt ha tilgang til offentlige medlemmer __INTERNAL_DATAi kroppen av konstruktøren.

Edit: som påpekt av James Curran, den __INTERNAL_DATAhar struktur ingen medlemmer, slik at den kan brukes som ovenfor, uten problemer.

Svarte 10/03/2009 kl. 20:16
kilden bruker

stemmer
1

Hvis typen er i en tredje part bibliotek da den store fordelen med frem erklæring (isolere ombygginger på grunn av endringer i overskrifter) er fullstendig tapt.

Hvis du er bekymret for kompilering ganger (det er en betydelig header) så kanskje du kan plassere den i en ferdigbygd header eller bare ta med den aktuelle heading fra et bibliotek.

F.eks mange bibliotek overskrifter ligne

// library.h
#include "Library/Something.h"
#include "Library/SomethingElse.h"
Svarte 10/03/2009 kl. 20:09
kilden bruker

stemmer
1
 typedef struct {} __INTERNAL_DATA, *HandleType;

Hvis det er definert sånn (alle på én linje), så __INTERNAL DATA er like mye en del av den offentlige grensesnitt som HandleType.

Men jeg tror ikke __INTERNAL_DATAegentlig eksisterer. Mer enn sannsynlig, er HandleType virkelig (internt) en int. Dette merkelig definisjon er bare en måte å definere det slik at det er samme størrelse som en int, men tydelig, slik at kompilatoren gi deg en feilmelding hvis du prøver å passere en int hvor du skal passere en HandleType. Biblioteket leverandøren kunne like gjerne har definert det som "int" eller "ugyldig *", men på denne måten får vi en slags kontroll.

Derfor __INTERNAL_DATAer bare en konvensjon og ikke kommer til å endre seg.


OPPDATERING: Ovennevnte var litt av en mental rap ... OK, __INTERNAL_DATAdefinitivt ikke eksisterer. Vi vet dette for et faktum, fordi vi kan se sin definisjon som en tom struct. Jeg kommer til å gjette at tredje-parts biblioteket bruker "C" ekstern lenke (ingen navn managling), i så fall, bare kopiere typedef - det vil bli bra.

Inne i biblioteket selv, HandleType vil ha en helt annen definisjon; kanskje int, kanskje "struct {MyStruct .......} *".

Svarte 10/03/2009 kl. 20:05
kilden bruker

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more