[C++]Overerving met andere parameters

Pagina: 1
Acties:

  • schoene
  • Registratie: Maart 2003
  • Laatst online: 21:42
Stel je hebt een basisklasse met een bepaalde functie 'foe':
C++:
1
2
3
4
5
6
7
8
class Base
{
public:
  int foe (int par1)
  {
  // ...
  }
};


en een overgeerfde klasse, die ook de functie 'foe' heeft, maar met een verschillend aantal parameters
C++:
1
2
3
4
5
6
7
8
class Inherited: public Base
{
public:
  int foe (int par1, int par2)
  {
  // ...
  }
};


Dan is de functie Base::foe niet meer beschikbaar voor een object van het type Inherited. Ik weet dat
je die functie weer beschikbaar kan maken door
C++:
1
using Base::foe;
aan de Inherited class toe te voegen, maar ik vraag me eigenlijk gewoon af waarom Base::foe niet meer beschikbaar is. Uiteindelijk heb je toch 2 functies met verschillend aantal parameters, en dus een andere signature? In een enkele klasse kan je ook 2 functies met dezelfde naam maar verschillend aantal parameters gebruiken, dus waarom niet met overgeerfde klasses?

  • L-VIS
  • Registratie: April 2005
  • Laatst online: 14-04 13:50
Waarom zet je beide functies niet in je base class. Je kunt van buitenaf bij beide functies komen.

C++:
1
2
3
4
5
6
class Base
{
public:
  int foe (int par1);
  int foe (int par1, int par2);
};

  • sys64738
  • Registratie: Oktober 2002
  • Laatst online: 23:02

sys64738

Moderator Foto & Video

Press play on tape

L-VIS schreef op donderdag 26 januari 2006 @ 10:02:
Waarom zet je beide functies niet in je base class. Je kunt van buitenaf bij beide functies komen.

C++:
1
2
3
4
5
6
class Base
{
public:
  int foe (int par1);
  int foe (int par1, int par2);
};
Omdat je dat niet wil?!? Kan me veel design keuzes/gevallen indenken waarom je dit niet zou willen. Raar dat dit niet kan inderdaad..... in java is dit geen enkel probleem.

Flickr | Photography 101: Skills > Patience > Gear


  • Zoijar
  • Registratie: September 2001
  • Niet online

Zoijar

Because he doesn't row...

He mag niet omdat het onduidelijk _kan_ zijn. In een diepe class hierarchie, in "the annotated C++ reference manual" hebben ze als voorbeeld 9 niveaus diep, kan het voorkomen dat je een functie toevoegt die toevallig dezelfde naam heeft als iets hoger in de hierarchie. Nu kan het voorkomen dat je die functie per ongeluk overload als er geen hiding rule was.

Het meest "vervelende" voorbeeld dat wordt gegeven is:

C++:
1
2
3
4
5
6
7
8
9
10
11
struct A {
   const A& operator=(int i) {...}
   A(int i) {}
};

struct B : public A {

};

B b1 = 1; // fortunate error due to name hiding
b1 = 2; // dito


Als er geen hiding werd gedaan zou alleen het base gedeelte gekopieerd of geinitialiseerd worden.

Argumenten zijn imho disputabel, maar de keuze is gemaakt, en de hiding rule is standaard, due je hebt je er maar aan te houden. Er is gekozen om de programmeur bewust overloads te laten kiezen (met using) ipv het misschien stilzwijgend fout te doen. Op zich wel goed.

  • Lethalis
  • Registratie: April 2002
  • Niet online
schoene schreef op donderdag 26 januari 2006 @ 09:53:
Uiteindelijk heb je toch 2 functies met verschillend aantal parameters, en dus een andere signature? In een enkele klasse kan je ook 2 functies met dezelfde naam maar verschillend aantal parameters gebruiken, dus waarom niet met overgeerfde klasses?
Misschien is het ambigu om signatures te verdelen over meerdere klassen? Dus dat base::foe wordt vervangen door inherited::foe en dat de enige manier om er weer bij te komen is door using base::foe te gebruiken.

Ask yourself if you are happy and then you cease to be.


  • schoene
  • Registratie: Maart 2003
  • Laatst online: 21:42
Lethalis schreef op donderdag 26 januari 2006 @ 10:42:
[...]

Misschien is het ambigu om signatures te verdelen over meerdere klassen? Dus dat base::foe wordt vervangen door inherited::foe en dat de enige manier om er weer bij te komen is door using base::foe te gebruiken.
Dat blijkt inderdaad ook zo te zijn, dat is duidelijk, maar ik vroeg me af waarom daar voor gekozen is.
Zoijar heeft wel een voorbeeld gegeven die iets verduidelijkt, hoewel dit niet slaat op het gebruik van functies met verschillend aantal argumenten. Een gelijkaardig voorbeeld is multiple inheritence, waarbij beide baseclasses eenzelfde functie hebben. Als ze hetzelfde aantal parameters hebben vind ik het logisch dat je in de overgeerfde klasse moet specificeren welke van de 2 functies je wil gebruiken, maar als de functies in de baseclasses een verschillend aantal parameters hebben moet je dit ook doen, en dat vind ik dan weer onlogisch

We moeten er ons maar aan houden, maar zo'n keuzes worden volgens mij toch niet zomaar gemaakt. Ik vermoed dat multiple inheritence en het meegeven van default parameters er toch wel wat mee te maken heeft.

edit: aantal vergeten in zin

[ Voor 3% gewijzigd door schoene op 26-01-2006 11:13 ]


  • Lethalis
  • Registratie: April 2002
  • Niet online
schoene schreef op donderdag 26 januari 2006 @ 10:58:
[...]
Zoijar heeft wel een voorbeeld gegeven die iets verduidelijkt, hoewel dit niet slaat op het gebruik van functies met verschillende argumenten.
Maar dat doet het juist wel. Het gaat hier puur om de hierarchie, niet zozeer om de parameters.

Ask yourself if you are happy and then you cease to be.


  • .oisyn
  • Registratie: September 2000
  • Nu online

.oisyn

Moderator Devschuur®

Demotivational Speaker

schoene schreef op donderdag 26 januari 2006 @ 10:58:
Ik vermoed dat multiple inheritence en het meegeven van default parameters er toch wel wat mee te maken heeft.
Nee, multiple inheritance en default parameters hebben er echt niets mee te maken. Het gaat puur om het feit dat als jij in een derived class een functie maakt met dezelfde naam, je meestal wilt dat die functie de functie uit de base class vervangt. Er is een reden dat je een functie met dezelfde naam toevoegt; over het algemeen moet ie ongeveer hetzelfde doen als die van de base class, maar toch net iets anders. En dan wil je dat, bij het gebruiken van een derived class, alleen die nieuwe functie gebruikt kan worden, omdat de oude eigenlijk nergens meer op slaat. De operator= was een goed voorbeeld, je kan een Fruit niet aan een Appel assignen, je kunt alleen een andere Appel aan een Appel assignen.

En het is gewoon een keuze: of de taal hide ze niet en dan moet je dat zelf doen (door ze bijv. in de derived als private te declaren), of ze worden standaard gehide en dan moet je opgeven dat je ze wilt importeren (middels een using declaration). En aangezien het hiden vaker voorkomt dan het andere is er voor de eerste oplossing gekozen.

(En het wordt er alleen maar inconsistenter op als je niet hide voor functies met een verschillend aantal argumenten, maar wel voor hetzelfde aantal)

[ Voor 6% gewijzigd door .oisyn op 26-01-2006 12:10 ]

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: 09-04 22:08
schoene schreef op donderdag 26 januari 2006 @ 09:53:
Stel je hebt een basisklasse met een bepaalde functie 'foe':
C++:
1
2
3
4
5
6
7
8
class Base
{
public:
  int foe (int par1)
  {
  // ...
  }
};


en een overgeerfde klasse, die ook de functie 'foe' heeft, maar met een verschillend aantal parameters
C++:
1
2
3
4
5
6
7
8
class Inherited: public Base
{
public:
  int foe (int par1, int par2)
  {
  // ...
  }
};
Dan heb je waarschijnlijk een design fout.

Het theoretische model voor inheritance is Liskov Substitutie. Inherited is-a Base als je een instance Inherited kunt gebruiken op elk punt waar een Base instance ook zou werken. dat is hier niet het geval, want in
C++:
1
2
3
void test(Base& b) {
    b.foe(1);
}
past volgens jouw opzet geen Inherited.

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


  • schoene
  • Registratie: Maart 2003
  • Laatst online: 21:42
mja, uiteindelijk was de basisklasse een collection, die een Search-functie had, en de inherited class had nog een extra Search functie, maar met een parameter minder. Het zoeken gebeurde iets anders, dus eigenlijk was het een slechte keuze om ze allebei dezelfde naam te geven. Uiteindelijk wel leuk dat je door een slechte keuze te maken weer iets nieuws leert :)
Pagina: 1