/ 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
overriding virtuelle metoder
Fra : James Wholar


Dato : 01-02-03 19:25

Måske subject ikke er særligt godt beskrivende.

Jeg er ved at lave nogen klasser til indpakning af en del opengl grafik.

Jeg har et CScene objekt med en virtuel metode render(...).
Helle verden skal så opbygges som en scene der indeholder andre scener, der
i sidte ende er objekter i verden.
Man laver ex et objekt som CTable som arver fra CScene. Implementerer render
for denne så den tegner et bord og alt er vel.

Nu vil jeg lave en CBillboard som arver fra CScene. Denne skal dog opføre
sig anderledes når render kaldes. Den skal først beregne en matrise for et
koodsystem hvor zaksen peger på et eye point, og derefter kalde render.

Jeg kan bare ikke lige overskue hvordan det gribes an. Hvis jeg lavet et
objekt som arver fra CBillboard og implementerer en render metode, så vil
denne implementation kaldes, og ikke billboards, som sætter denne matrise.
Man kan så lave en metode i billboard som sætter matrisen og en anden som
fjerner den igen efter render, men det betyder at man altid skal huske, for
objekter der arver fra billboard, at starte render med SetMatrix og slutte
med clearMAtrix. Det er ikke videre heldigt da det kan glemmes og bør ske
automatisk, før render kaldes og igen efter den er kaldt.

Jeg ville gerne have en effekt af at når render kaldes for et objekt der
arver fra billboard, så bliver billboards render kaldt, denne sætter
matrisen og kalder childs render, og når den returnerer så fjernes matrisen
igen.

Men.. hvordan kan dette gøres?

Kort opsummeret, så ønsker jeg at specialisere render funktionen i
cbillboard sådan at denne specialisering rammer alle children af billboard.
Nogen tips?



 
 
Ole Nielsby (01-02-2003)
Kommentar
Fra : Ole Nielsby


Dato : 01-02-03 23:50


James Wholar skrev:

> Måske subject ikke er særligt godt beskrivende.
>
> Jeg er ved at lave nogen klasser til indpakning af en del opengl grafik.
>
> Jeg har et CScene objekt med en virtuel metode render(...).
> [...]
> Man laver ex et objekt som CTable som arver fra CScene. Implementerer
render
> for denne så den tegner et bord og alt er vel.
>
> Nu vil jeg lave en CBillboard som arver fra CScene. Denne skal dog opføre
> sig anderledes når render kaldes. Den skal først beregne en matrise for et
> koodsystem hvor zaksen peger på et eye point, og derefter kalde render.
>
> Jeg kan bare ikke lige overskue hvordan det gribes an. Hvis jeg lavet et
> objekt som arver fra CBillboard og implementerer en render metode, så vil
> denne implementation kaldes, og ikke billboards, som sætter denne matrise.
> Man kan så lave en metode i billboard som sætter matrisen og en anden som
> fjerner den igen efter render, men det betyder at man altid skal huske,
for
> objekter der arver fra billboard, at starte render med SetMatrix og slutte
> med clearMAtrix. Det er ikke videre heldigt da det kan glemmes og bør ske
> automatisk, før render kaldes og igen efter den er kaldt.
>
> Jeg ville gerne have en effekt af at når render kaldes for et objekt der
> arver fra billboard, så bliver billboards render kaldt, denne sætter
> matrisen og kalder childs render, og når den returnerer så fjernes
matrisen
> igen.

Her er en opskrift som jeg ikke har prøvet - men den skulle gøre det
muligt.

Første skridt er at du definerer en virtual InnerRender metode i CBillboard.
CBillboard.Render() sætter matricen, kalder InnerRender og fjerner
matricen igen. (Brug en try-finally så matricen også fjernes efter fejl.)

Du kan nu overskrive InnerRender i stedet for at overskrive Render.

Men du vil formentlig hellere have at den ny metode hedder det samme
som den gamle - altså at når man overskriver Render, er det den nye
metode man overskriver.

Det kan du opnå ved andet skridt:

Omdøb CBillboard til interimCBillboard, lav den abstrakt og lav en ny
klasse CBillboard som arver fra den. I den ny CBillboard erklærer du
en ny virtuel Render-metode med samme signatur (new, C# spec. 3.7.1.2)
og lader InnerRender kalde den.

Herefter kan du subclasse CBillboard og overskrive Render-metoden
med det ønskede resultat.

Du bør lave en rebuild af dit projekt efter omdøbningen.

Hvis du bruger "sealed" (C# specs 10.5.5) på interimCBillboard.Render
og Billboard.InnerRender, har JIT-compileren gode muligheder for at
bortoptimere noget af det overhead der introduceres ved at kalde
gennem den ekstra procedure.

ON/Fjern sneglen fra min svaradresse



James Wholar (02-02-2003)
Kommentar
Fra : James Wholar


Dato : 02-02-03 07:53

> Første skridt er at du definerer en virtual InnerRender metode i
CBillboard.
> CBillboard.Render() sætter matricen, kalder InnerRender og fjerner
> matricen igen. (Brug en try-finally så matricen også fjernes efter fejl.)
>
> Du kan nu overskrive InnerRender i stedet for at overskrive Render.

Det var også hvad jeg kom frem til her i nat mens jeg sov.

> Men du vil formentlig hellere have at den ny metode hedder det samme
> som den gamle - altså at når man overskriver Render, er det den nye
> metode man overskriver.
>
> Det kan du opnå ved andet skridt:
>
> Omdøb CBillboard til interimCBillboard, lav den abstrakt og lav en ny
> klasse CBillboard som arver fra den. I den ny CBillboard erklærer du
> en ny virtuel Render-metode med samme signatur (new, C# spec. 3.7.1.2)
> og lader InnerRender kalde den.
>
> Herefter kan du subclasse CBillboard og overskrive Render-metoden
> med det ønskede resultat.

Ok, det var en ekstra detalje. En ok ide faktisk. Takker.
Men hvorfor taler du om c# specs? På disse punkter adskilder c# sig da fra
c++, gør det ikke?
try finally er mig bekendt heller ikke med i c++, men i pascal oa?


> Hvis du bruger "sealed" (C# specs 10.5.5) på interimCBillboard.Render
> og Billboard.InnerRender, har JIT-compileren gode muligheder for at
> bortoptimere noget af det overhead der introduceres ved at kalde
> gennem den ekstra procedure.
>
> ON/Fjern sneglen fra min svaradresse

sealed?



Ole Nielsby (03-02-2003)
Kommentar
Fra : Ole Nielsby


Dato : 03-02-03 03:43


James Wholar skrev:

> Men hvorfor taler du om c# specs? På disse punkter adskilder c# sig
> da fra c++, gør det ikke?
> try finally er mig bekendt heller ikke med i c++, men i pascal oa?

Undskyld. Af en eller anden grund forvekslede jeg denne NG
med dk.edb.programmering.dotnet . Jeg er ikke C++ -haj og
ved ikke om C++ tilbyder den mulighed jeg skitserede i C#.

ON/Fjern sneglen fra min svaradresse


Mogens Hansen (02-02-2003)
Kommentar
Fra : Mogens Hansen


Dato : 02-02-03 08:30


"James Wholar" <_@_.a> wrote

[8<8<8<]
> Men.. hvordan kan dette gøres?

Du kan måske bruge design patternet "Template Method" (om ikke har noget med
C++ templates at gøre).
Det findes beskrevet i bogen:
Design Patterns: Elements of Reusable Object-Oriented Software
Erich Gamma, Richard Helm, Ralph Johnson, John Vlissides
ISBN 0-201-63361-2

Det vil kunne se ca. sådan ud:

<code>
#include <iostream>

using std::cout; using std::endl;

class scene
{
public:
scene();
virtual ~scene();

void render(); // not virtual

protected:
virtual void pre_render();
virtual void do_render() = 0;
virtual void post_render();

private:
// copy constructor and copy assignment
// delcared but not implemented, to prevent
// accidental usage
scene(const scene&);
scene& operator=(const scene&);
};

class billboard : public scene
{
protected:
virtual void pre_render();
virtual void do_render();
virtual void post_render();
};

class table : public billboard
{
protected:
virtual void do_render();
};


inline scene::scene()
{
}

inline scene:scene()
{
}

void scene::render()
{
pre_render();
do_render();
post_render();
}

void scene::pre_render()
{
cout << "scene::pre_render" << endl;
}

void scene::post_render()
{
cout << "scene::post_render" << endl;
}


void billboard::pre_render()
{
cout << "billboard::pre_render" << endl;
cout << "setup matrix" << endl;
}

void billboard::do_render()
{
cout << "billboard::do_render" << endl;
}

void billboard::post_render()
{
cout << "billboard::post_render" << endl;
cout << "cleanup matrix" << endl;
}


void table::do_render()
{
cout << "table::do_render" << endl;
}

void test_render(scene& scene_arg)
{
scene_arg.render();
}

int main()
{
table t;
test_render(t);
}

</code>

Venlig hilsen

Mogens Hansen



Søg
Reklame
Statistik
Spørgsmål : 177491
Tips : 31966
Nyheder : 719565
Indlæg : 6408458
Brugere : 218886

Månedens bedste
Årets bedste
Sidste års bedste