/ 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
Implementering af et interface via nedarvn~
Fra : Thomas Krog


Dato : 23-09-01 21:29

Her er et eksemel hvor interfacet C implementeres i klassen D via nedarvning
fra klassen B:
class A{
virtual void test() = 0;
};
class B : public A{
void test(){}
};
class C : public A{};

class D : public B,public C{};

int main(){
D d;
return 0;
}

Både vc++ og g++ mener dog at D er en abstrakt klasse og tillader derfor
ikke at der bliver oprettet en instans af typen D. Problemet kan løses ved
at skrive:
class D : public B,public C{
void test(){
B::test();
}
};

Men så ryger noget af ideen ved nedarvning jo lidt - findes der ikke en
løsning?

I java er der ingen problemer med at lave et sådan hierarki (så det må da
også kunne lade sig gøre i c++):
interface A{
public void test();
}
class B implements A{
public void test(){}
}
interface C extends A{}
class D extends B implements C{}
class Inheritance{
public static void main(String[] args){
D d = new D();
}
}



 
 
Mogens Hansen (24-09-2001)
Kommentar
Fra : Mogens Hansen


Dato : 24-09-01 06:00


"Thomas Krog" <rick@kampsax.dtu.dk> wrote in message
news:9olgnm$85o$1@eising.k-net.dk...

>
> Men så ryger noget af ideen ved nedarvning jo lidt - findes der ikke en
> løsning?

Jo - du har selv givet en mulig løsning.

Hvorfor ryger ideen med nedarvning ?
Det vigtige ved nedarvning er at klasser der arver fra A, kan bruges på alle
steder hvor A benyttes (Liskov substitution principle).
Det vigtige er _ikke_ kode-genbrug eller hvor lidt man skal skrive.

>
> I java er der ingen problemer med at lave et sådan hierarki (så det må da
> også kunne lade sig gøre i c++):

Blot fordi noget kan lade sig gøre i Java er det ikke ensbetydende med at
det kan lade sig gøre i C++ - og omvendt.
Det er 2 _meget_ forskellige sprog.

Java's "fordel" i denne sammenhæng, er at det understøtter ikke multiple arv
fra konkrete klasser (kun fra interfaces).

Hvis nu _både_ B _og_ C implementerer test:

class A{
public:
virtual void test(void) = 0;
};
class B : public A{
public:
void test(void){}
};
class C : public A
{
public:
void test(void){}
};

hvilken skulle så kaldes når D::test kaldes ?
Der er 3 muligheder:
* B::test
* C::test
* først B::test og derefter C::test
Compileren kan ikke afgøre hvilken af de 3 der kunne være rigtig i den givne
sammenhæng.
Det må du som programmøren afgøre.

Hvis den første mulighed er rigtig, kan man skrive

class D : public B,public C
{
using B::test;
};

int main(){
D d;
return 0;
}



Venlig hilsen

Mogens Hansen



Thomas Krog (24-09-2001)
Kommentar
Fra : Thomas Krog


Dato : 24-09-01 12:51

> Hvorfor ryger ideen med nedarvning ?
> Det vigtige ved nedarvning er at klasser der arver fra A, kan bruges på
alle
> steder hvor A benyttes (Liskov substitution principle).
> Det vigtige er _ikke_ kode-genbrug eller hvor lidt man skal skrive.

Det er heller ikke så meget kode-genbrug jeg tænker på, men mere det at gøre
D "uafhængig" af A og B. Hvis man fx. har 100 klasser der som D alle
nedarver fra B og C så er det upraktisk at man ikke kan tilføje en funktion
som test() i eksemplet uden at man skal ændre i de 100 underklasser.

> hvilken skulle så kaldes når D::test kaldes ?
> Der er 3 muligheder:
> * B::test
> * C::test
> * først B::test og derefter C::test
> Compileren kan ikke afgøre hvilken af de 3 der kunne være rigtig i den
givne
> sammenhæng.
> Det må du som programmøren afgøre.

Godt argument - så giver det lidt mere mening med det ekstra kode i D



Kent Friis (24-09-2001)
Kommentar
Fra : Kent Friis


Dato : 24-09-01 16:39

Den Mon, 24 Sep 2001 13:51:00 +0200 skrev Thomas Krog:
>> Hvorfor ryger ideen med nedarvning ?
>> Det vigtige ved nedarvning er at klasser der arver fra A, kan bruges på
>alle
>> steder hvor A benyttes (Liskov substitution principle).
>> Det vigtige er _ikke_ kode-genbrug eller hvor lidt man skal skrive.
>
>Det er heller ikke så meget kode-genbrug jeg tænker på, men mere det at gøre
>D "uafhængig" af A og B. Hvis man fx. har 100 klasser der som D alle
>nedarver fra B og C så er det upraktisk at man ikke kan tilføje en funktion
>som test() i eksemplet uden at man skal ændre i de 100 underklasser.

Tror du så ikke du skulle lade Q arve fra B og C, og D1 - D100 arve
fra Q?

Mvh
Kent
--
8:16pm up 2:37, 1 user, load average: 101.21, 95.46, 55.85
164 processes: 62 sleeping, 102 running, 0 zombie, 0 stopped

With XMMS tugging along nicely, playing Vivaldi...

Thomas Krog (24-09-2001)
Kommentar
Fra : Thomas Krog


Dato : 24-09-01 17:22

> >Det er heller ikke så meget kode-genbrug jeg tænker på, men mere det at
gøre
> >D "uafhængig" af A og B. Hvis man fx. har 100 klasser der som D alle
> >nedarver fra B og C så er det upraktisk at man ikke kan tilføje en
funktion
> >som test() i eksemplet uden at man skal ændre i de 100 underklasser.
>
> Tror du så ikke du skulle lade Q arve fra B og C, og D1 - D100 arve
> fra Q?

Den mulighed havde jeg totalt overset - skræmmende ;)



Per Abrahamsen (24-09-2001)
Kommentar
Fra : Per Abrahamsen


Dato : 24-09-01 15:06

"Thomas Krog" <rick@kampsax.dtu.dk> writes:

> class A{
> virtual void test() = 0;
> };
> class B : public A{
> void test(){}
> };
> class C : public A{};
>
> class D : public B,public C{};
>
> int main(){
> D d;
> return 0;
> }

D indeholder to A'er i dette eksempel, nemlig D::B::A og D::C::A, og
A::test er kun implementeret for den ene, nemlig D::B::A::test.
D::C::A::test er stadig uimplementeret.

> class D : public B,public C{
> void test(){
> B::test();
> }
> };

Her implementerer du begge A::test functioner.

> Men så ryger noget af ideen ved nedarvning jo lidt - findes der ikke en
> løsning?

Hvis du gerne vil have to A'er, er den løsning du selv har givet
korrekt. Det er helt almindeligt at man gerne vil have to instanser
af superklassen. Tænk f.eks. på en vertikalt beregningslag med en
øvre rand og en nedre rand, der begge arver fra en fælles rand
klasse. Eftersom der modelmæssigt er tale om to forskellige rande, vil
det logiske være at der er to instanser af rand klassen i sit
beregningslag.

Jeg kan ikke lige komme på et eksempel hvor det logiske vil være kun
at have en instans af den fælles superklasse, men det kan du jo nok.
I den slags tilfælde kan man bruge virtuel nedarvning. Det betyder at
klasserne i nedarvningshierarkiet skal deles om samme instans, og
så¨vil dit eksempel virke.

class A{
virtual void test() = 0;
};
class B : virtual public A{
void test(){}
};
class C : virtual public A{};

class D : public B,public C{};

int main(){
D d;
return 0;
}

Thomas Krog (24-09-2001)
Kommentar
Fra : Thomas Krog


Dato : 24-09-01 17:11

> Jeg kan ikke lige komme på et eksempel hvor det logiske vil være kun
> at have en instans af den fælles superklasse, men det kan du jo nok.
> I den slags tilfælde kan man bruge virtuel nedarvning. Det betyder at
> klasserne i nedarvningshierarkiet skal deles om samme instans, og
> så¨vil dit eksempel virke.
>
> class A{
> virtual void test() = 0;
> };
> class B : virtual public A{
> void test(){}
> };
> class C : virtual public A{};
>
> class D : public B,public C{};
>
> int main(){
> D d;
> return 0;
> }

Det var lige det jeg var ude efter. Tak for det!

Det skal bruges i en raytracer hvor:
-alle objekter har et materiale
-nogle objekter er solid
-nogle objekter er basic objekter

hierarkiet ser (i korte træk) således ud (for at undgå at Sphere får to
materialer):

class GeoObject{
public:
const Material& getMat() const = 0;
};
class MaterialObject : virtual public GeoObject{
Material m;
public:
const Material& getMat() const{return m;}
};
class BasicObject : virtual public GeoObject{
GeoVector getNormal(const GeoVector& pos) const;
};
class SolidObject : public MaterialObject{};

class Sphere : public BasicObject, public SolidObject {};

class BooleanObject : public SolidObject {
SolidObject* a;
SolidObject* b;
};
class Polygon : public BasicObject{};



Søg
Reklame
Statistik
Spørgsmål : 177501
Tips : 31968
Nyheder : 719565
Indlæg : 6408522
Brugere : 218887

Månedens bedste
Årets bedste
Sidste års bedste