Toon posts:

[c++,beginner] Constructor dubbel vanwege klein verschil?

Pagina: 1
Acties:

Verwijderd

Topicstarter
Hallo,
Ik wil een nieuw object op 2 manieren kunnen maken met een heel klein verschil in de aanroep. Moet ik dan de hele constructor 2 keer opschrijven of is er een kortere notatie voor?

Het gaat om de volgende constructor (uit kde's katepart):
C++:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
KateStyleListItem::KateStyleListItem( QListViewItem *parent, const QString & stylename,
                              KateAttribute *style, KateHlItemData *data )
        : QListViewItem( parent, stylename ),
          ds( style ),
          st( data )
{
  if (!st)
    is = ds;
  else
  {
    is = new KateAttribute (*style);

    if (data->isSomethingSet())
      *is += *data;
  }
}

KateStyleListItem::KateStyleListItem( QListView *parent, const QString & stylename,
                              KateAttribute *style, KateHlItemData *data )
        : QListViewItem( parent, stylename ),
          ds( style ),
          st( data )
{
  if (!st)
    is = ds;
  else
  {
    is = new KateAttribute (*style);

    if (data->isSomethingSet())
      *is += *data;
  }
}
De constructor moet zowel kunnen worden aangeroepen met een QListView* als met een QListViewItem* als eerste argument. Deze worden gelijk aan de superclass doorgegeven. Voor de rest zijn de constructors gelijk. Is hier geen handigere notatie voor? Kan in mijn C++ boek niets vinden.

[ Voor 3% gewijzigd door Verwijderd op 20-05-2004 20:18 ]


Verwijderd

Topicstarter
Helaas, dat lukt me niet.

Gek genoeg stammen ze alleen heel ver af van Qt. Maar als ik dat erneer zet krijg ik een foutmelding:
code:
1
2
3
4
5
6
7
8
9
10
11
kateschema.cpp: In constructor `KateStyleListItem::KateStyleListItem(Qt*, const
   QString&, KateAttribute*, KateHlItemData*)':
kateschema.cpp:1130: error: call of overloaded `QListViewItem(Qt*&, const
   QString&)' is ambiguous
/usr/qt/3/include/qlistview.h:86: error: candidates are:
   QListViewItem::QListViewItem(QListViewItem*, QString, QString, QString,
   QString, QString, QString, QString, QString) <near match>
/usr/qt/3/include/qlistview.h:81: error:
   QListViewItem::QListViewItem(QListView*, QString, QString, QString, QString,
   QString, QString, QString, QString) <near match>
make: *** [kateschema.lo] Fout 1
want die superclass lust ook maar 2 soorten.

Als ik er void neerzet krijg ik dit:
code:
1
2
3
4
5
6
7
8
9
10
11
kateschema.cpp: In constructor `KateStyleListItem::KateStyleListItem(void*,
   const QString&, KateAttribute*, KateHlItemData*)':
kateschema.cpp:1130: error: call of overloaded `QListViewItem(void*&, const
   QString&)' is ambiguous
/usr/qt/3/include/qlistview.h:86: error: candidates are:
   QListViewItem::QListViewItem(QListViewItem*, QString, QString, QString,
   QString, QString, QString, QString, QString) <near match>
/usr/qt/3/include/qlistview.h:81: error:
   QListViewItem::QListViewItem(QListView*, QString, QString, QString, QString,
   QString, QString, QString, QString) <near match>
make: *** [kateschema.lo] Fout 1

kortom hetzelfde.

  • talpje
  • Registratie: Februari 2001
  • Laatst online: 31-07-2025
Dan kan het dus niet op een andere manier, aangezien de constructors die je direct aanroept ook strict gescheiden constructors zijn... dus zit er niets anders op om zelf ook 2 te maken...

Je zou de rest van de code in je constructor natuurlijk wel in een Init() functie kunnen zetten en die in beide constructors aanroepen zodat je niet al je code dubbel hebt :) (Is redelijk standaard practice om te doen)

mekkerrrrrrrrrrrr


Verwijderd

Topicstarter
bedankt!

  • Zoijar
  • Registratie: September 2001
  • Niet online

Zoijar

Because he doesn't row...

Verwijderd schreef op 20 mei 2004 @ 20:37:
Helaas, dat lukt me niet.

Gek genoeg stammen ze alleen heel ver af van Qt. Maar als ik dat erneer zet krijg
En kan je het niet met static_cast<Qt*>(q) aanroepen, dat zou de ambiguiteit moeten resolven. Of zoiets in ieder geval, het is mij een beetje onduidelijk wat precies wat is. Maar je krijgt een ambiguity error, dat betekent dat de compiler twee keuzes heeft die allebei 'even goed' zijn. Dus dan moet jij als programmeur aangeven welke van die twee je nou bedoelt.

[ Voor 4% gewijzigd door Zoijar op 21-05-2004 13:16 ]


  • MSalters
  • Registratie: Juni 2001
  • Laatst online: 09-04 22:08
Je kunt geen common base class gebruiken voor parent, omdat je "parent" door moet geven aan je base class. Daarbij is het verschil belangrijk, dat mag je niet weg gooien.

Er is wel een oplossing:
C++:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
template< typename ParentT >
KateStyleListItem::KateStyleListItem( ParentT *parent, const QString & stylename, 
                              KateAttribute *style, KateHlItemData *data ) 
        : QListViewItem( parent, stylename ), 
          ds( style ), 
          st( data ) 
{ 
  if (!st) 
    is = ds; 
  else 
  { 
    is = new KateAttribute (*style); 

    if (data->isSomethingSet()) 
      *is += *data; 
  } 
}

Let op, templates gaan in .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


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

.oisyn

Moderator Devschuur®

Demotivational Speaker

Je kunt de code in de constructors natuurlijk ook in een private member function gooien, en die vanuit de constructors aanroepen

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
Nee, dat lijkt maar zo. Let op regel 4, waar parent wordt gebruikt in een base class initializer.

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


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

.oisyn

Moderator Devschuur®

Demotivational Speaker

Je leest mijn reply verkeerd, ik heb het over de code tussen de accolades :)
Dit stukje dus:
C++:
1
2
3
4
5
6
7
8
9
  if (!st)  
    is = ds;  
  else  
  {  
    is = new KateAttribute (*style);  

    if (data->isSomethingSet())  
      *is += *data;  
  }  

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.


  • Alarmnummer
  • Registratie: Juli 2001
  • Laatst online: 09-07-2024

Alarmnummer

-= Tja =-

[algemeen geblaat]
Als je meerdere constructors hebt die vanuit een andere context worden aangeroepen, bv:

code:
1
2
3
4
5
class Persoon{
     Persoon(String name, boolean man){....}

     Persoon(String name, boolean man, Persoon vader, Persoon moeder){...}
}

De 1e constructor die wordt aangeroepen voor adam en voor eva. De andere constructor moet aangeroepen worden voor normale mensen. Het kan dan handig zijn om factory methods te maken waaruit duidelijker blijkt wat de bedoeling ervan is:

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
class Persoon{

    static Persoon createAdam(){return new Persoon("adam",true)}

    static Persoon createEva(){return new Persoon("eva",false)}

    static Persoon 
    createNormalPersoon(String name, boolean man, Persoon v, Persoon m){
           return new Persoon(name,man,v,m);
    }
  
    ...constructors
}


Op die manier kan je aan de naam van de build methode veel beter aflezen wat je nu aan het doen bent ipv dat je uit het aantal en type van de argumenten moet afleiden wat je aan het doen bent.

In refactoring to patterns staat hier trouwens een heel leuk stuk over. De preview kun je gratis ophalen op: www.industriallogic.com/xp/refactoring

[ Voor 3% gewijzigd door Alarmnummer op 24-05-2004 09:32 ]


Verwijderd

Topicstarter
thanks, ik heb de code idd in een private init() functietje gezet

  • curry684
  • Registratie: Juni 2000
  • Laatst online: 12-05 22:23

curry684

left part of the evil twins

Verwijderd schreef op 24 mei 2004 @ 12:09:
thanks, ik heb de code idd in een private init() functietje gezet
Mental note voordat je er tegen de mist in gaat: die Init-functie mag nooit van z'n leven virtual gemaakt worden of een virtual functie via-via aanroepen. Just for the record, heb ik per ongeluk 1 keer fout gedaan en dan kun je verdomd lang naar je probleem zoeken :)

Professionele website nodig?


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

.oisyn

Moderator Devschuur®

Demotivational Speaker

Alarmnummer schreef op 24 mei 2004 @ 09:31:
.. java-achtige ontwerptechnieken ..
Da's wel leuk, zolang je je objecten aanmaakt met new. In C++ hoeft dat niet, en je wilt de gebruiker eigenlijk niet forceren om dat te doen. Het kan wel, maar dan moet je kopies gaan returnen, en dat is lang niet altijd wat je wilt

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
curry684 schreef op 24 mei 2004 @ 12:36:
[...]

Mental note voordat je er tegen de mist in gaat: die Init-functie mag nooit van z'n leven virtual gemaakt worden of een virtual functie via-via aanroepen. Just for the record, heb ik per ongeluk 1 keer fout gedaan en dan kun je verdomd lang naar je probleem zoeken :)
Hoezo? Omdat het binnen de ctor gebeurt maakt het helemaal niets uit; je krijgt in beide gevallen (al dan niet virtual) Base::Init als je Init() aanroept vanuit Base::Base().

Reden: totdat Derived::Derived begint (na de { ) is het 'object under construction' nog geen Derived, maar een Base.

Het enige wat je dus niet moet doen is pure virtual, non-implemented functies aanroepen.

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


  • Eelis
  • Registratie: Januari 2003
  • Laatst online: 21-02-2015
.

[ Voor 101% gewijzigd door Eelis op 18-02-2015 19:33 ]


  • curry684
  • Registratie: Juni 2000
  • Laatst online: 12-05 22:23

curry684

left part of the evil twins

MSalters schreef op 24 mei 2004 @ 17:16:
[...]

Hoezo? Omdat het binnen de ctor gebeurt maakt het helemaal niets uit; je krijgt in beide gevallen (al dan niet virtual) Base::Init als je Init() aanroept vanuit Base::Base().
Gezien het feit dat dat op het eerste gezicht niet normaal gedrag is leek de waarschuwing me niet ongepast :+

Professionele website nodig?

Pagina: 1