Dårligt OO design?
Dårligt OO design?
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?
[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?
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.
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?
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.
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?
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]
[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.
Mente du:
[c]class Derived: public A, public MyBase
{
}[-c]
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' :tandersen wrote:Compileren har dog ikke noget problem med det
[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?
Ja, du har fuldkommen ret - en lille svipser..Mente du:
[c]class Derived: public A, public MyBase
{
}[-c]
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?
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
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.
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
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?
Igen, rigtig rart at vide!Hvis du vil snakke om kæmpe overhead, så prøv og dump et dynamic_cast<> i et af dine inner loops.
Re: Dårligt OO design?
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'
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'