Dårligt OO design?

cluq
Level 2 - Grain of sand
Posts: 24
Joined: 11 Mar 2008, 15:50

Dårligt OO design?

Unread post by cluq » 31 Mar 2008, 15:48

Jeg har et OO design problem. Jeg har følgende klassestruktur:

[c]class Base
{
virtual void pureVirtualMethod() = 0;
}

Class MyBase: public Base
{
}

class A: public Base
{
virtual void pureVirtualMethod();
}

Class Derived: public A, public MyBase
{
}
[-c]

Første problem er at klassen Derived nedarver to gange fra Base (igennem A og igennem MyBase). Desuden implementerer Derived pureVirtualMethod() igennem A::pureVirtualMethod(), men MyBase()::pureVirtualMethod() er stadig pure virtual - hvordan dælen håndterer compileren det?

Er det her bare et tegn på generelt dårlig objekt orienteret design? :)

tandersen
Level 0 - Null
Posts: 3
Joined: 31 Mar 2008, 21:34

Re: Dårligt OO design?

Unread post by tandersen » 31 Mar 2008, 21:41

Det er helt klar uoptimalt oo design! Diamond shape inheritance er noget du skal prøve at undgå med al magt.

Compileren har dog ikke noget problem med det. Du ender med 2 instanser af base klassen. Hvilket gør at du som programmør vil blive temmeligt forvirret :) .

Hvis du vil tvinge compileren til kun at instantiere klassen en gang, skal du bruge "virtual inheritance", men det har også en række begrænsninger + et ekstra 4 byte overhead per instans.

cluq
Level 2 - Grain of sand
Posts: 24
Joined: 11 Mar 2008, 15:50

Re: Dårligt OO design?

Unread post by cluq » 01 Apr 2008, 13:30

Ja, jeg har også bestemt mig for at det må være dårligt design - men rart at få sat et ord på :)

Jeg har løst det på følgende måde (ikke at dette er en generel løsning, men det kan accepteres i mit tilfælde):

[c]class Base
{
virtual void pureVirtualMethod() = 0;
}

Class MyBase
{
}

class A: public Base
{
virtual void pureVirtualMethod();
}

Class Derived: public A, public MyBase, public Base
{
}[-c]

MyBase arver ikke længere fra Base, men til gengæld arver Derived nu fra både MyBase og fra Base.

dasapfe
Level 1 - Speck of dust
Posts: 17
Joined: 08 Mar 2008, 16:10

Re: Dårligt OO design?

Unread post by dasapfe » 02 Apr 2008, 00:45

Du sagde i din første post at problemet var at Derived nedarvede fra Base 2 gange, men i det kode du har postet nedarver du stadigvæk fra Base 2 gange (explicit, og gennem A) ... :?:

Mente du:
[c]class Derived: public A, public MyBase
{
}[-c]
tandersen wrote:Compileren har dog ikke noget problem med det
Det har den faktisk, fordi den ikke kan finde ud af hvilken af de 2 funktioner den skal kalde. Forestil (for simplicitetens skyld) at 'Base' indeholdt en 'int foo' :
[c]Derived der;
der.foo = 0; // "ambiguous access of 'foo'"
der.A::Base::foo = 1; // Ok
der.MyBase::Base::foo = 2; // Ok
[-c]

Forresten er det ikke kun "ekstra 4 byte overhead per instans", men derimod størrelsen af en pointer per klasse der har virtuel nedarving. I cluq's første tilfælde ville det blive til 8 byte på et 32-bit system, og 16 byte på et 64-bit system, osv. Det gode ved det er dog at Base kun findes én gang, så hvis den har en masse data bliver besparelsen det værd.

cluq
Level 2 - Grain of sand
Posts: 24
Joined: 11 Mar 2008, 15:50

Re: Dårligt OO design?

Unread post by cluq » 03 Apr 2008, 09:25

Mente du:
[c]class Derived: public A, public MyBase
{
}[-c]
Ja, du har fuldkommen ret - en lille svipser..

Men det er fedt at få diskuteret virtual inheritence og virtual metoder generelt. Jeg har været nysgerrig omkring hvor meget overhead der var i, at man lavede en metode virtual. Jeg mener, hvis man laver en .lib eller .dll (lad os for sjov skyld antage at det er en spilengine :lol: ), så vil man jo så vidt muligt, give "brugeren" af lib'en mulighed for selv at udvide og specialisere klasser og metoder - og derfor må mange metoder jo laves virtual. Men hvis der er kæmpe overhead når man kalder en virtual metode, så bliver man jo netop nødt til at minimere brugen af virtual..

dasapfe
Level 1 - Speck of dust
Posts: 17
Joined: 08 Mar 2008, 16:10

Re: Dårligt OO design?

Unread post by dasapfe » 03 Apr 2008, 13:59

Det er meget lidt overhead der kommer når man bruger virtual metoder. I langt de fleste tilfælde er compileren klog nok til at tage den hurtigste vej, og det resulterer som regel kun i en ekstra jmp instruktion hver gang man kalder en virtual metode. :)

Hvis du vil snakke om kæmpe overhead, så prøv og dump et dynamic_cast<> i et af dine inner loops. Fy for satan :D

Med hensyn til at lade brugerne af din spilengine udvide den, så er scripting jo altid en mulighed. Der findes færdige løsninger, såsom lua, men det er også spas at lave sit eget sprog der er skræddersyet til spillet.

cluq
Level 2 - Grain of sand
Posts: 24
Joined: 11 Mar 2008, 15:50

Re: Dårligt OO design?

Unread post by cluq » 04 Apr 2008, 15:18

Hvis du vil snakke om kæmpe overhead, så prøv og dump et dynamic_cast<> i et af dine inner loops.
Igen, rigtig rart at vide! :)

dasapfe
Level 1 - Speck of dust
Posts: 17
Joined: 08 Mar 2008, 16:10

Re: Dårligt OO design?

Unread post by dasapfe » 05 Apr 2008, 20:41

Mere information end du nogensinde får brug for.

En mere generel, og rigtig god og sjov, guide til mange af C++' særheder kan findes her. Man ved det er langhåret når nogle af sektionerne indles med et 'This might hurt your head; better if you sit down' :D

Post Reply