Toon posts:

[C++] Inheritance en instantiation

Pagina: 1
Acties:

Verwijderd

Topicstarter
Ik ben nog niet zolang met C++ bezig en ben nu tegen een probleempje aangelopen mbt inheritance.

Laat ik maar meteen met de deur in huis vallen: ik heb een class Polygon en een class Rectangle, die inherit van Polygon. In de class Rectangle is een functie area() gedefinieerd die de oppervlakte van de rechthoek returned:

code:
1
2
3
4
5
6
7
8
9
10
11
class Polygon {
  protected:
      int width, height;
  public:
      void setValues(int a, int b) {width=a; height=b;}
};

class Rectangle: public Polygon {
  public:
      int area(void) {return (width*height);}
};


In mijn main doe ik dit:

code:
1
2
3
4
5
6
int main() {
  Polygon * pol = new Rectangle;

  pol->setValues(4,5);
  cout << pol->area(); << endl;
}


Maar ik krijg nu de foutmelding dat Polygon geen functie area() bevat. Hoe moet ik dit anders aanpakken? Ik wil bijvoorbeeld nog een class Triangle toevoegen en dan in mijn code alle triangles en rectangles aanspreken alsof het polygons zijn. Wat je doet met abstract classes in Java dus.

/edit: typo

[ Voor 8% gewijzigd door Verwijderd op 06-03-2003 03:02 ]


  • hobbit_be
  • Registratie: November 2002
  • Laatst online: 04-07-2025
behalve je typefout (figuur moet pol zijn toch?) is het nogal simpel: je zegt dat pol een Polygon is en een polygon heeft geen Area(). JIJ weet wel dat pol eigenlijk een Rectangle is maar je zult dus een cast moeten doen ala ((Rectangle*)pol).area; (of hoe het nu ook weeral zit met de haakjes:).

eerlijk gezegd logisch is je code dus al niet :). en vergeet ook niet dat C++ geen Java.

wat je wel kan doen is in Polygon een virtual area() zetten die niets doet en als je er dan nog =0 vanachter zet heb je eigenlijk een interface zoals Java.

case of bad design...

  • whoami
  • Registratie: December 2000
  • Laatst online: 23:02
hobbit_be schreef op 06 maart 2003 @ 02:37:
behalve je typefout (figuur moet pol zijn toch?) is het nogal simpel: je zegt dat pol een Polygon is en een polygon heeft geen Area(). JIJ weet wel dat pol eigenlijk een Rectangle is maar je zult dus een cast moeten doen ala ((Rectangle*)pol).area; (of hoe het nu ook weeral zit met de haakjes:).

eerlijk gezegd logisch is je code dus al niet :). en vergeet ook niet dat C++ geen Java.

wat je wel kan doen is in Polygon een virtual area() zetten die niets doet en als je er dan nog =0 vanachter zet heb je eigenlijk een interface zoals Java.

case of bad design...


Hm.... Ik zou toch voor die 2de oplossing gaan, niet voor dat casten. ;)
Gebruik maken van polymorphisme is toch veel mooier en flexibeler dan in je code 'hard' te gaan casten.

https://fgheysels.github.io/


  • Korben
  • Registratie: Januari 2001
  • Laatst online: 14-11-2025

Korben

() => {};

hobbit_be schreef op 06 maart 2003 @ 02:37:
... ((Rectangle*)pol).area; (of hoe het nu ook weeral zit met de haakjes:).
C++:
1
2
3
4
5
((Rectangle *) pol)->area();

// of

*((Rectangle *) pol).area();
Waarbij uiteraard de eerste het meest elegant is :)

.oisyn: Échte programmeurs haten PHP met een passie. Ben jij soms geen echte programmeur?


  • whoami
  • Registratie: December 2000
  • Laatst online: 23:02
Het elegantste is imho nog altijd dit (hobbit_be's 2de voorgestelde alternatief dus):

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public class Polygon
{

  protected:
     int width, height;

  public:
      void setValues (int w, int h);
      virtual void getArea()=0;
};

public Rectangle : public Polygon
{

  public:
     void getArea();
};


En dan in de code:
code:
1
2
3
Polygon* pol = new Rectangle();
pol->setValues(5, 5);
pol->getArea();

[ Voor 15% gewijzigd door whoami op 06-03-2003 09:46 ]

https://fgheysels.github.io/


  • MSalters
  • Registratie: Juni 2001
  • Laatst online: 21-08 17:14
setValues is onzinnig op een Polygon. Op zich is het niet zo erg; dat kunnen gewoon de twee argumenten van een Rectangle ctor zijn.

In C++ cast je netjes via een dynamic_cast; als je dan een ander type dan je dacht hebt krijg je een null-pointer. Bovendien kun je veel makkelijker in je code zoeken naar de tekst "dynamic_cast" dan naar een C-stijl cast.

PS. als je met shapes werkt bij inheritance, bedenk dan dat je shapes niet kunt veranderen nadat ze gemaakt zijn. Anders zou je een hoekpunt van een polygon kunnen veranderen, maar niet van een rectangle. Consequentie: rectangle is dan geen polygon meer.

Man hopes. Genius creates. Ralph Waldo Emerson
Never worry about theory as long as the machinery does what it's supposed to do. R. A. Heinlein


  • Zoijar
  • Registratie: September 2001
  • Niet online

Zoijar

Because he doesn't row...

Dit is ook iha slecht design, een rectangle is een specifieke polygon. Dat is not done, een class die inherit heeft altijd meer functionaliteit. Dit is exact het "cirlce-is-a-elipse" probleem, lees eens hier

  • Nexopheus
  • Registratie: Juni 2001
  • Laatst online: 28-01 13:50
Volgens mij gaat het daar niet echt om, [je hebt geen ongelijk hoor] maar de TS wil denk ik gewoon een beetje stoeien met C++ om zo de taal meester te krijgen. [no offence...]

Wat niet kan is nog nooit gebeurd


  • whoami
  • Registratie: December 2000
  • Laatst online: 23:02
Zoijar schreef op 06 March 2003 @ 11:40:
Dit is ook iha slecht design, een rectangle is een specifieke polygon. Dat is not done, een class die inherit heeft altijd meer functionaliteit. Dit is exact het "cirlce-is-a-elipse" probleem, lees eens hier


Ipv met het 'is a ' principe te werken, kan je ook met het 'has a' idee werken.
(Alhoewel dit in dit specifieke voorbeeld niet echt veel meer nut biedt dan het is a principe)

https://fgheysels.github.io/


  • Zoijar
  • Registratie: September 2001
  • Niet online

Zoijar

Because he doesn't row...

Nexopheus schreef op 06 March 2003 @ 11:57:
Volgens mij gaat het daar niet echt om, [je hebt geen ongelijk hoor] maar de TS wil denk ik gewoon een beetje stoeien met C++ om zo de taal meester te krijgen. [no offence...]
Als je iets aan het leren bent, leer het dan meteen goed :-)

  • Zoijar
  • Registratie: September 2001
  • Niet online

Zoijar

Because he doesn't row...

whoami schreef op 06 March 2003 @ 12:08:


Ipv met het 'is a ' principe te werken, kan je ook met het 'has a' idee werken.
(Alhoewel dit in dit specifieke voorbeeld niet echt veel meer nut biedt dan het is a principe)
"has-a" is volgens mij private/protected inheritance, public inheritance is altijd "is-a". Hoewel die termen soms een beetje vaag en niet toepasselijk zijn.

  • Nexopheus
  • Registratie: Juni 2001
  • Laatst online: 28-01 13:50
Helemaal mee eens.

Wat niet kan is nog nooit gebeurd


  • whoami
  • Registratie: December 2000
  • Laatst online: 23:02
Zoijar schreef op 06 March 2003 @ 12:11:
[...]


"has-a" is volgens mij private/protected inheritance, public inheritance is altijd "is-a". Hoewel die termen soms een beetje vaag en niet toepasselijk zijn.


'Has a' is het samenstellen van objecten ipv het inheriten van classes. Samenstellen is meestal veel flexibeler dan overerven.

https://fgheysels.github.io/


  • Nexopheus
  • Registratie: Juni 2001
  • Laatst online: 28-01 13:50
composition, aggregation tegen over inheritance ... toch?

Wat niet kan is nog nooit gebeurd


  • Glimi
  • Registratie: Augustus 2000
  • Niet online

Glimi

Designer Drugs

(overleden)
Nexopheus schreef op 06 March 2003 @ 12:18:
composition, aggregation tegen over inheritance ... toch?

Jupz :) Echter ik ben zowieso niet zo'n voorstander van inheritance in deze context.

Ik probeer meestal zo veel mogelijk te werken met interfaces, extenties daarop en abstracte classes. Aan het eind van de classtree hangen dan nog wat concrete classes, die allemaal van een abstracte class extenden en niet van elkaar.

Hiermee probeer ik zulk soort problemen als hierboven te voorkomen. Immers een Vierkant is een polygoon, echter een 'speciale'. Door dit speciale zijn veel eigenschappen die bij een polygoon erzijn ( adden 6 van punten bijv, om een vierhoek te maken) er niet bij een vierkant ( 2 punten adden voor 4 punten, en niet meer dan 2 punten )

  • Krooswijk.com
  • Registratie: Mei 2000
  • Laatst online: 17-08-2024
kijk eens op www.cplusplus.com en zoek op 'virtual' daar staat een goed toegelicht voorbeeld dat ook gebruik maakt van cpolygon en crectangle als het goed is...

  • Zoijar
  • Registratie: September 2001
  • Niet online

Zoijar

Because he doesn't row...

Nexopheus schreef op 06 maart 2003 @ 12:18:
composition, aggregation tegen over inheritance ... toch?
In principe ook nog association, dat vrijwel gelijk is aan aggregation met het verschil dat er geen ownership over het geassocieerde object is. Zo zijn bv de wielen van een auto iha aggregated, en de passagiers associated.

Nog iets anders:
"A car has-a wheel"
"A car has-a passenger"
"A car has-a(n) engine"

Dit zijn drie verschillende has-a's.
De eerste is aggregation/member-pointer; er is ownership over de wielen, als de auto destroyed wordt zo ook de wielen.
De tweede is association/member-pointer; als de auto destroyed wordt blijft de passagier(persoon) vrolijk leven. Er kunnen andere wielen onder een auto gezet worden.
De derde is aggregation/inheritance; er is ownership, en de motor is onlosmakelijk verbonden met de auto. private inheritance dus.

[ Voor 42% gewijzigd door Zoijar op 06-03-2003 13:20 ]


  • hobbit_be
  • Registratie: November 2002
  • Laatst online: 04-07-2025
Zoijar schreef op 06 March 2003 @ 13:12:
[...]
Nog iets anders:
"A car has-a wheel"
"A car has-a passenger"
"A car has-a(n) engine"
nou dat hangt ermaar van af van je design he... ik ben van het standpunt dat een car gewoon een samenhangsel is:

a car -might have n wheels ( dus gewoon reference naar x-aantal wheels)
a car -might have n passengers ( "")
a car -must have an engine (ref naar een engine object) maar dat een
car inheretence heeft van een engine? das is grofweg fout. welke member functions zou een car-concept van/een engine overnemen??? is dus ook een aggregation member.

net als Glimi ben ik voor 'interfaces' or 'contracts' dit hide de hele rompslomp of iets nou wel of niet member is of niet. Gebruik van referenced object maakt ook de hele has-a an non-issue. Ze verdwijnen wanneer niemand hem 'gebruikt'. Interfaces hebben ook het leuke aspect dat als je toch iets veranderd je implemting classes niet moeten worden hercompileerd.

  • MSalters
  • Registratie: Juni 2001
  • Laatst online: 21-08 17:14
Private inheritance betekent "Is-implemented-as-a", niet "has-a".
De reden ligt in multipliciteit: has-a sluit niet uit dat je er twee van hebt. is-a/is-implemented-as-a sluit dat wel uit. Je kunt wel twee members van een bepaald type hebben, maar geen twee (directe) bases van eenzelfde type.

Man hopes. Genius creates. Ralph Waldo Emerson
Never worry about theory as long as the machinery does what it's supposed to do. R. A. Heinlein


  • Zoijar
  • Registratie: September 2001
  • Niet online

Zoijar

Because he doesn't row...

hobbit_be schreef op 06 maart 2003 @ 13:48:

nou dat hangt ermaar van af van je design he...
Yep helemaal mee eens, maar iha als voorbeeld gezien.
ik ben van het standpunt dat een car gewoon een samenhangsel is:

a car -might have n wheels ( dus gewoon reference naar x-aantal wheels)
Wie owned die wheels dan? Wat gebeurt er als je auto verwijderd wordt? Worden de wielen ook verwijderd, of kan je een wiel zonder auto hebben? Verder is dit precies wat ik zei, aggregation/association zijn in implementatie in C++ vrijwel altijd references dan wel pointers naar de andere objecten. Aleen specificeerde ik er nog ownership bij dmv het een aggregation te noemen.
a car -might have n passengers ( "")
Zelfde verhaal als boven.
a car -must have an engine (ref naar een engine object) maar dat een
car inheretence heeft van een engine? das is grofweg fout. welke member functions zou een car-concept van/een engine overnemen??? is dus ook een aggregation member.
Let wel private inheritance, dat is niet hetzelfde als normale, public, inheritance. Private inheritance staat voor een aggregation, alleen kan ik nu die reference niet wijzigen en dus niet per ongeluk er ineens een andere motor aan hangen; iets dat niet mocht (onlosmakelijk verbonden)
net als Glimi ben ik voor 'interfaces' or 'contracts' dit hide de hele rompslomp of iets nou wel of niet member is of niet. Gebruik van referenced object maakt ook de hele has-a an non-issue. Ze verdwijnen wanneer niemand hem 'gebruikt'. Interfaces hebben ook het leuke aspect dat als je toch iets veranderd je implemting classes niet moeten worden hercompileerd.
Dit staat compleet los van het al dan niet gebruiken van interfaces. Ik zou zeggen combineer het. Je kan bv een associated of een aggregated list (een list die niet resp wel zijn elementen owned) schrijven met een interface voor insertions etc erop.

En zeggen "ik gebruik smart pointers, dus ik hoef me niet druk te maken om ownership" is een beetje iets vaags. Je wilt toch in beginsel je ontwerp goed hebben? En objecten verdwijnen niet zo maar in C++ hoor ;)

  • hobbit_be
  • Registratie: November 2002
  • Laatst online: 04-07-2025
dat van private inheritance wist ik niet - ook niet dat dat kon :). Komt dus eigenlijk neer op een interface MET implementatie. Gebruik van 'smart-pointers' is idd ook niet altijd ideal omdat ze nog steeds moeten 'unreffed' worden in destructors. Maar dan nog doe je maar een 'unref' ok elk object dat de class gebruikt - als het echt eigen was aan de class dan verdwijnt het, if not (iemand anders heeft nog een ref) dan niet. Dat vb met wheel: ik neem steeds aan dat een wheel gewoon een object is dat verwisselbaar is. Of als ie versleten is daar een dopcap van afvalt :) Maar hangt af van waarvoor het gebruikt moet worden natuurlijk. Ma ja kzal beter me mond houden want gaan discussieren over een fictief voorbeeld :) ...

Verwijderd

Topicstarter
Zohee, veel reakties.

Dit was maar een stom voorbeeld trouwens, met polygonen, vierkanten etc.

Maar ik heb het wel door nu :D, als ik me de term polymorphisme herinnerd had was ik er zelf ook wel uitgekomen :o. Maar ja, wordt een beetje lastig zoeken he, als je het beestje niet bij zijn naam weet te noemen...

Toch nog een klein ander vraagje: moeten classes die inheriten van elkaar in 1 header file worden gedefinieerd? Als ik ze namelijk in aparte files zet geeft mijn compiler (g++) foutmeldingen... Of ik krijg resultaten die ik niet verwacht, maar daar heb ik zo gauw even geen voorbeeld van, was iets te enthousiast met het deleten van al mijn experimentjes.

[ Voor 15% gewijzigd door Verwijderd op 07-03-2003 03:19 ]


  • whoami
  • Registratie: December 2000
  • Laatst online: 23:02
Je moet ze afaik niet in dezelfde header file definieren. Wat je wel moet doen is de nodige headers includen.

https://fgheysels.github.io/


Verwijderd

Topicstarter
whoami schreef op 07 March 2003 @ 09:05:
Je moet ze afaik niet in dezelfde header file definieren. Wat je wel moet doen is de nodige headers includen.
:?

Is dat 1337 ofzo? Wat betekent dit nou weer?

  • Soultaker
  • Registratie: September 2000
  • Laatst online: 22-08 01:56
Verwijderd schreef op 09 maart 2003 @ 22:23:
:?

Is dat 1337 ofzo? Wat betekent dit nou weer?
As far as I know; voor zover ik weet.

Verwijderd

Verwijderd schreef op 07 maart 2003 @ 03:18:
Zohee, veel reakties.

Dit was maar een stom voorbeeld trouwens, met polygonen, vierkanten etc.

Maar ik heb het wel door nu :D, als ik me de term polymorphisme herinnerd had was ik er zelf ook wel uitgekomen :o. Maar ja, wordt een beetje lastig zoeken he, als je het beestje niet bij zijn naam weet te noemen...

Toch nog een klein ander vraagje: moeten classes die inheriten van elkaar in 1 header file worden gedefinieerd? Als ik ze namelijk in aparte files zet geeft mijn compiler (g++) foutmeldingen... Of ik krijg resultaten die ik niet verwacht, maar daar heb ik zo gauw even geen voorbeeld van, was iets te enthousiast met het deleten van al mijn experimentjes.
Nee, nee, nee.
Laten we aub duidelijk houden. Implementatie in een cpp file en de header stuff in een h file. Als je met interfaces en factories werkt dan mag je alles in een cpp file stoppen en heb je alleen een h file voor je interface. Headers files gewoon apart includen, denk eraan dat je je code maar een keer schrijft en misschien nog wel 100x leest.

  • hobbit_be
  • Registratie: November 2002
  • Laatst online: 04-07-2025
Verwijderd schreef op 09 March 2003 @ 22:47:
[...]
Nee, nee, nee.
Laten we aub duidelijk houden. Implementatie in een cpp file en de header stuff in een h file. Als je met interfaces en factories werkt dan mag je alles in een cpp file stoppen en heb je alleen een h file voor je interface. Headers files gewoon apart includen, denk eraan dat je je code maar een keer schrijft en misschien nog wel 100x leest.
en toen had je templates :)...

  • whoami
  • Registratie: December 2000
  • Laatst online: 23:02
hobbit_be schreef op 10 March 2003 @ 03:19:
[...]


en toen had je templates :)...


:?

Wat heeft dit te maken met de post die je gequote hebt? Ik zie niet in waar ik templates kan inpassen met die post....

https://fgheysels.github.io/


  • .oisyn
  • Registratie: September 2000
  • Laatst online: 22-08 13:19

.oisyn

Moderator Devschuur®

Demotivational Speaker

hobbit_be schreef op 10 maart 2003 @ 03:19:
en toen had je templates :)...


en toen was er een export directive, wat ervoor zorgt dat je de implementatie niet in een header hoeft te zetten maar gewoon kunt compilen naar een object-file/library ;)

(wordt wel weinig ondersteund overigens, ik geloof dat comeau de enige is)

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


  • MSalters
  • Registratie: Juni 2001
  • Laatst online: 21-08 17:14
Je kunt natuurlijk ook je .cpp file met template implementatie includen in je .h :)

Man hopes. Genius creates. Ralph Waldo Emerson
Never worry about theory as long as the machinery does what it's supposed to do. R. A. Heinlein


  • curry684
  • Registratie: Juni 2000
  • Laatst online: 13-08 16:46

curry684

left part of the evil twins

MSalters schreef op 10 March 2003 @ 12:39:
Je kunt natuurlijk ook je .cpp file met template implementatie includen in je .h :)
Gatver :D

Professionele website nodig?


  • Glimi
  • Registratie: Augustus 2000
  • Niet online

Glimi

Designer Drugs

(overleden)

Welke andere optie raad je aan dan? Aangezien een .tmpl includen in je .h "eigenlijk" hetzelfde is en export alleen door comeau geïmplementeerd wordt :) zie ik eig. alleen nog maar het coden in de .h zelf en dat is helemaal erg :P

  • curry684
  • Registratie: Juni 2000
  • Laatst online: 13-08 16:46

curry684

left part of the evil twins

Glimi schreef op 10 March 2003 @ 13:26:

[...]

Welke andere optie raad je aan dan? Aangezien een .tmpl includen in je .h "eigenlijk" hetzelfde is en export alleen door comeau geïmplementeerd wordt :) zie ik eig. alleen nog maar het coden in de .h zelf en dat is helemaal erg :P
.inl?

curry684 in "templates in c++"

[ Voor 11% gewijzigd door curry684 op 10-03-2003 13:33 . Reden: Linkje d'r bij ]

Professionele website nodig?


  • hobbit_be
  • Registratie: November 2002
  • Laatst online: 04-07-2025
am i missing the point?:

bij templates is de implementatie toch steeds in de .h file? *zelfs met inlines/comeau. Je kan bij templates de implementatie toch niet ECHT scheiden van de definite aangezien ie net de code genereert... Of hebben ze daar ook al een oplossing voor gevonden?

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 22-08 13:19

.oisyn

Moderator Devschuur®

Demotivational Speaker

hobbit_be: die optie bestaat allang: definieer je template class of functie met export:

C++:
1
2
3
4
5
6
7
8
9
10
export template <class T>
class TemplateClass
{
private:
    T t;

public:
    T & get ();
    void set (const T &);
};


de implementatie kan in een cpp die gecompiled kan worden (nou ja, echt compilen gebeurt natuurlijk pas als de template class met een bepaald type geinstantieerd wordt). Dit resulteert dus in een extra compile stap die tijdens linken gedaan wordt.

.edit: hmm ik zie dat mijn highlighter het export keyword niet herkent :P

[ Voor 8% gewijzigd door .oisyn op 10-03-2003 14:43 ]

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


  • hobbit_be
  • Registratie: November 2002
  • Laatst online: 04-07-2025
.oisyn:

en zou ie dan zo slim zijn om voor elke 'type' (van je template dus) een obj file bij te houden om zo sneller te (her)compileren? zou wel handig zijn . Die export kende ik niet en maakt hel wel 'mooier' om te onderscheiden zo, weet weer wat doen.

zo en zijn al die source-syntax gevallen van jouw hier? dacht gisteren: dit is wel handig voor documentatie op mijn site als ik nou eens telkens als ik code wou weergeven een post met code tags op Got loslaat dan de output rippen en op mijn site zetten :))) . Maw wat zijn de terms and conditions van die gevallen. en nog straighter to the point: is die code Open-Source? :)))
Pagina: 1