[C++] overloading probleem

Pagina: 1
Acties:

  • ReverendBizarre
  • Registratie: December 2001
  • Laatst online: 24-03-2021
Ik wilde een stuk code schrijven wat de volgende structuur heeft:

Een basis klasse met een public method:
C++:
1
2
3
4
5
6
7
8
class CBase
{
public:
    void Test(int number)
    {
        cout << "Base test\n";
    }
};



Een afgeleide klasse daarvan met een method met dezelfde naam maar een andere argumenten lijst en dus een andere signature.
C++:
1
2
3
4
5
6
7
8
9
class CSomeClass : public CBase
{
public:

    void Test(string &text)
    {
        cout << "Some Class test\n";
    }
};


En vervolgens een stukje code om dat mee te testen...
C++:
1
2
3
4
5
6
7
8
9
10
int _tmain(int argc, _TCHAR* argv[])
{
    CSomeClass  obj;
    string      text = "hoi";

    obj.Test(1);
    obj.Test(text);

    return 0;
}


Ik ging er van uit dat dit zou werken en dat het mogelijk was om methodes uit de basis klasse te overloaden zonder dat dit de methode van de basis klasse onzichtbaar maakt. Maar dit blijkt dus niet zo te zijn. De regel

C++:
1
obj.Test(1);


geeft als foutmelding dat parameter 1 niet van int naar std::string geconverteerd kan worden. Met andere woorden hij roept dus CSomeClass::Test() aan terwijl CBase::Test() de methode is die ik bedoelde aan te roepen. Als je beide Test() methoden in dezelfde class neerzet werkt het overloaden prima dus ik ging er van uit dat dit concept ook van toepassing is van klasse op klasse.

Een simpele oplossing hiervoor is natuurlijk om gewoon een andere naam te gebruiken in de afgeleide klasse maar ik zou toch graag een alternatieve implementatie voor een bestaande methode in de basis class willen specificeren (met andere argumenten lijst dus) zonder deze compleet te overriden.

Is dit inderdaad onmogelijk en zo ja, weet iemand ook waarom? (ja, ik vindt dat soort dingen interessant)

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 22-05 23:07

.oisyn

Moderator Devschuur®

Demotivational Speaker

.edit: hier stond onzin, ik moet beter lezen



Nu een wel goede uitleg :P
Een functie in een derived class verbergt alle functies uit de base klasse met dezelfde naam. Je kunt het oplossen door een using CBase::Test in CSomeClass op te nemen.

[ Voor 159% gewijzigd door .oisyn op 20-08-2004 00:52 ]

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.


  • Zoijar
  • Registratie: September 2001
  • Niet online

Zoijar

Because he doesn't row...

Hmmm ik kan me iets herinneren over scope hiding...;compiler geeft ook een warning toch? Weet even niet zo snel wat het precies was, of wat de rationale was...staat ergens in de standaard ;)

Ah ^^^ da'was't. Kwam dit niet voor bij het visitor pattern?

[ Voor 15% gewijzigd door Zoijar op 20-08-2004 00:55 ]


  • ReverendBizarre
  • Registratie: December 2001
  • Laatst online: 24-03-2021
Aah. Helemaal geweldig.

Ik had me al rot zitten Googlen maar ik kon het maar niet vinden omdat ik ook niet zo goed kon bedenken waarop ik nou moest zoeken.

Bedankt!

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 22-05 23:07

.oisyn

Moderator Devschuur®

Demotivational Speaker

Zoijar schreef op 20 augustus 2004 @ 00:53:
Kwam dit niet voor bij het visitor pattern?
Nee, die is gebaseerd op de regel dat altijd de overload wordt gekozen waar een zo klein mogelijke conversie voor nodig 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.


  • Zoijar
  • Registratie: September 2001
  • Niet online

Zoijar

Because he doesn't row...

Ik zie het al, dat was idd als je niet alle visit operaties overload in een derivation van de visitor interface (bv voor default behaviour). De defaults worden dan hidden. Dus of alles overloaded, of de using directive. [pattern hatching, vlissides, p36]

Verwijderd

Hmmm... ik heb nog nooit zo zien overloaden.

Toch zou het technisch gesproken waarschijnlijk wel moeten kunnen... (al heb ik mijn bedenkingen of het nuttig is... :/).

Ik heb helaas niet genoeg C++ kennis om je vraag te beantwoorden.

  • Zoijar
  • Registratie: September 2001
  • Niet online

Zoijar

Because he doesn't row...

Verwijderd schreef op 20 augustus 2004 @ 01:18:
Ik heb helaas niet genoeg C++ kennis om je vraag te beantwoorden.
Gelukkig heeft oisyn hem al beantwoord ;)

  • ReverendBizarre
  • Registratie: December 2001
  • Laatst online: 24-03-2021
Is dit echt zo raar om te doen dan? Mij leek het een vrij logische constructie en niet meer of minder nuttig dan kunnen overloaden binnen dezelfde class. Maar het is mogelijk dat wat ik probeer te doen een bad practice is. (ik ben nog altijd druk bezig om alle OO principes onder de knie te krijgen)

Dit is de context van mijn programma:

Ik heb een class geschreven die een container encapsuleert (std::vector) en die een template argument meeneemt wat beschrijft welk type deze class opslaat.

In deze basis class heb ik naast een aantal Sort() routines ook generieke Insert() methode die als argument het template type meeneemt.

Vervolgens heb ik van deze basis class twee concrete classes gemaakt die allebei een specifiek type kunnen opslaan. Dus...

C++:
1
2
3
4
5
6
7
template <class someType> 
class SomeList
{
   ...
   void Insert(someType item);
   ...
}


en...

C++:
1
2
3
4
5
6
7
8
9
class ListType1 : public SomeList<type1>
{
  ...
}

class ListType2 : public SomeList<type2>
{
   ...
}


Als je bijvoorbeeld ListType1 instantieert kan je gewoon Insert() aanroepen met een variabele van het type "type1". Maar ik wilde naast deze bestaande methode dus nog een nieuwe Insert() methode in ListType1 toevoegen met een andere argumenten lijst. Bijvoorbeeld een methode die ipv een object van het type1 gewoon de losse velden als argument accepteert:

C++:
1
void Insert(string &field1, string &field2, int field3);


Dat was eigenlijk alles wat ik van plan was. Dit probeerde ik dus te doen en toen kreeg ik dus het probleem dat de Insert() methode van mijn basis class ineens niet meer aan te roepen was.

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 22-05 23:07

.oisyn

Moderator Devschuur®

Demotivational Speaker

Waarom maak je die string references niet const?

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.


  • Zoijar
  • Registratie: September 2001
  • Niet online

Zoijar

Because he doesn't row...

Waarom maak je derived classes voor de specifieke types? Daar zijn typdefs, en eventueel template specializations voor. Dus:

C++:
1
2
3
4
5
6
7
typedef SomeList<std::string> StringList;

template <>
class SomeList<std::string> {
public:
   void Insert(...);
};

Dat idee.

  • ReverendBizarre
  • Registratie: December 2001
  • Laatst online: 24-03-2021
In mijn code zijn deze ook const. Alle code in mijn posts zit ik gewoon uit mijn hoofd te tikken en dat was ik dus even vergeten.

Wat betreft het gebruik van classes, beide typen hebben een verschillende set van sorting methodes bovenop de standaard sort methodes van de basis klasse. Het zijn dus geen lege class definities ofzo.

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 22-05 23:07

.oisyn

Moderator Devschuur®

Demotivational Speaker

Zoijar: En dan mag je fijn alle code van SomeList<T> nog eens gaan herhalen ;)

[ Voor 17% gewijzigd door .oisyn op 20-08-2004 02:16 ]

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.


  • Soultaker
  • Registratie: September 2000
  • Laatst online: 23-05 18:13
Als je toch met templates aan de slag gaat kun je waarschijnlijk ook wel een template method overriden. Sowieso lijkt een template-constructie me vooral nuttig als je je code wil kunnen parametriseren; die trucjes met template specialisatie zijn leuk, maar helder noch nodig.

Gewone method overloading lijkt me hier de meest logische keuze, ook als je daar vanwege de typische C++-raarheid weer een extra declaratie (using ...) bij nodig hebt.

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 22-05 23:07

.oisyn

Moderator Devschuur®

Demotivational Speaker

Mwoa, raarheid? Er is wel wat voor te zeggen, je maakt een specialisatie van een functie in een gespecialiseerde klasse. Vaak wil je voorkomen dat de minder gespecialiseerde functies van de base classes dan worden aangeroepen.

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.


  • Soultaker
  • Registratie: September 2000
  • Laatst online: 23-05 18:13
Ik zie niet echt hoe een functie met een string-argument meer gespecialiseerd is dan een functie met een int-argument. Als het type van het 'nieuwe' argument nu een subtype was van het 'oude' argument, zou ik me er iets bij voor kunnen stellen, maar nu zijn het (zoals de topic starter al stelt) eigenlijk twee verschillende methoden met twee onafhankelijke signatures. Omdat de naam (slechts 1 onderdeel van zo'n method signature) 'toevallig' hetzelfde is wordt de oude methode verborgen.

Ik kan me er wel iets bij voorstellen maar ik vind het niet overduidelijk de logische oplossing; op basis van de genoemde argumenten was het naar mijn idee geen uitzonderingsregel waard (C++ heeft al veel te veel kleine regeltjes die op zichzelf niet direct onzinnig zijn, maar de taal als geheel nogal complex maken). Het kan natuurlijk zijn dat er nog andere overwegingen meespelen bij de rechtvaardiging van deze ontwerpkeuze waar ik me niet bewust van ben.

  • MSalters
  • Registratie: Juni 2001
  • Laatst online: 09-04 22:08
Bij het selecteren van een overload wordt maar naar een scope tegelijk gekeken. Dat is juist om de complexiteit te verkleinen, in het bijzonder met Multiple Inheritance. Als je compiler je naar een bepaalde class wijst, weet je dat daarin alle overwogen overloads staan. Dit is minder beperkend dan het lijkt, vanwege de using-directive.

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


  • Dutchmega
  • Registratie: September 2001
  • Niet online
offtopic:
Is dit nou C++ of C++ .NET? of zijn er nog meer versies ;)

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 22-05 23:07

.oisyn

Moderator Devschuur®

Demotivational Speaker

ik zie geen .net in de titel staan hoor ;)

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
Wat is C++.NET? VC++.NET is versie 7 van de MSVC compiler, een applicatie dus. C++/CLI en MC++ zijn twee extensies op standaard ISO C++, allebei talen van MS voor de .NET CLR. Maakt de zaak wat verwarrend als je die door elkaar gooit.

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

Pagina: 1