Page 1 of 1

Dårligt OO design?

Posted: 31 Mar 2008, 15:48
by cluq
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? :)

Re: Dårligt OO design?

Posted: 31 Mar 2008, 21:41
by tandersen
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.

Re: Dårligt OO design?

Posted: 01 Apr 2008, 13:30
by cluq
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.

Re: Dårligt OO design?

Posted: 02 Apr 2008, 00:45
by dasapfe
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.

Re: Dårligt OO design?

Posted: 03 Apr 2008, 09:25
by cluq
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..

Re: Dårligt OO design?

Posted: 03 Apr 2008, 13:59
by dasapfe
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.

Re: Dårligt OO design?

Posted: 04 Apr 2008, 15:18
by cluq
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! :)

Re: Dårligt OO design?

Posted: 05 Apr 2008, 20:41
by dasapfe
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