Check alle échte Black Friday-deals Ook zo moe van nepaanbiedingen? Wij laten alleen échte deals zien

[C++] Implicit conversion naar base class?

Pagina: 1
Acties:

  • Gehakt
  • Registratie: Juli 2002
  • Laatst online: 24-10 20:19
Ik kwam zojuist een stukje code tegen waarvan ik niet wist dat het werkte en ik vraag me dan ook af of dat iemand me kan vertellen hoe het werkt?

Stel we hebben een Base en een Derived klasse.
C++:
1
2
Derived derived;
Base base = derived;

Bovenstaande compileert zonder problemen zonder dat in Base een conversion constructor is geschreven. Het mechanisme werkt ook niet door middel van een conversie constructor. Dit denk ik omdat ik de constructor handmatig heb geschreven private heb gemaakt. Dit maakte geen enkel verschil.

Doet de compiler een simpele memcopy oid van de waarden in het object omdat ze toch in dezelfde volgorde in het geheugen liggen?

De standaard C++ sites hebben me nog niet echt verder geholpen.

  • wjvds
  • Registratie: Mei 2012
  • Laatst online: 19-11 05:21
Waar jij volgens mij op doelt is een eigenschap van inheritance. Zo ziet dat er in je memory eruit.

  • Gehakt
  • Registratie: Juli 2002
  • Laatst online: 24-10 20:19
Ik heb het al opgelost. De compiler genereert WEL een conversion constructor. Ik dacht dat ik hem zelf had gedefinieerd en dat deze niet aangeroepen werd. Ik had er echter het keyword "explicit" voorgezet waardoor de compiler hem alsnog zelf genereerde.

Nadat ik dit keyword had weggehaald kreeg ik wel een compiler error dat de constructor private was :-)

Voor de volledigheid:
De compiler genereert dus zoiets:
C++:
1
2
3
4
Base::Base(const Derived& derived) :
    m_value(derived.m_value)
{
}

[ Voor 17% gewijzigd door Gehakt op 09-06-2013 20:10 ]


Verwijderd

Pas wel op met de construct uit de topicstart. Als je dat doet treed er een effect op wat slicing heet, base is dan mogelijk niet meer terug te dynamic_casten naar derived.

  • Gehakt
  • Registratie: Juli 2002
  • Laatst online: 24-10 20:19
Het lijkt me inderdaad evident dat je Base niet meer naar Derived kan casten. Je hebt immers simpelweg een deel van de informatie weg gesliced.

Ik kende het begrip nog niet. Dank daarvoor.

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 01:09

.oisyn

Moderator Devschuur®

Demotivational Speaker

Gehakt schreef op zondag 09 juni 2013 @ 20:02:
Ik heb het al opgelost. De compiler genereert WEL een conversion constructor.
Nee, dat doet ie niet. Wat de compiler genereert is een copy constructor. Jouw code komt uiteindelijk in de gegenereerde Base::Base(const Base &) terecht.

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.


  • Gehakt
  • Registratie: Juli 2002
  • Laatst online: 24-10 20:19
.oisyn schreef op zondag 09 juni 2013 @ 21:51:
[...]

Nee, dat doet ie niet. Wat de compiler genereert is een copy constructor. Jouw code komt uiteindelijk in de gegenereerde Base::Base(const Base &) terecht.
Dit snap ik niet helemaal? Als ik de copy constructor van Base(const Derived&) private maak dan krijg ik een compiler error en als ik de code draai met deze constructor public dan breakt de debugger daar ook.
Daaruit concludeer ik dus dat compiler deze
C++:
1
Base::Base(const Derived& derived)
constructor genereert als ik deze niet zelf heb geschreven net als dat de compiler dat doet voor standaard constructors en standaard copy constructors.
Ik ben benieuwd waarom je denkt dat het anders werkt?

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 01:09

.oisyn

Moderator Devschuur®

Demotivational Speaker

Gehakt schreef op zondag 09 juni 2013 @ 23:30:
[...]

Dit snap ik niet helemaal? Als ik de copy constructor van Base(const Derived&)
Dat is een conversion constructor, geen copy constructor
private maak dan krijg ik een compiler error
Logisch, want Base(const Derived&) is een betere kandidaat dan Base(const Base&), en dus wordt die gekozen bij de overload resolution. Alleen is ie private, dus een error.
en als ik de code draai met deze constructor public dan breakt de debugger daar ook.
Zie boven. Niet meer private, dus geen error.
Ik ben benieuwd waarom je denkt dat het anders werkt?
Dat denk ik niet alleen, dat weet ik ;). De enige constructors die door de compiler gegenereerd worden zijn default ctors indien er geen andere ctors gedefinieerd zijn, en copy ctors indien er geen andere ctor gegenereerd is met een cv Base& als eerste parameter (en eventueel defaulted volgende parameters).

Aangezien jij geen ctor definieert met een cv Base& zal de compiler dat dus doen. En dat is een prima kandidaat om aan te roepen als jij verder geen ctor definieert die een Derived accepteert, want een Derived is immers impliciet converteerbaar naar Base. Ook als je 'm wel definieert maar explicit maakt dan is dat in jouw codevoorbeeld geen kandidaat om aan te roepen (er is immers geen expliciete context) en zal de copy ctor worden aangeroepen.

[ Voor 5% gewijzigd door .oisyn op 09-06-2013 23:50 ]

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.


  • Gehakt
  • Registratie: Juli 2002
  • Laatst online: 24-10 20:19
Wat een magische taal is dat C++ toch. Ik snap je verhaal. Morgen nog eens proberen dan :-)

  • MSalters
  • Registratie: Juni 2001
  • Laatst online: 13-09 00:05
Niets bijzonders, Java werkt ook zo. Liskov Substitution Principle: een Derived object is-een Base object omdat een Derived object overal gebruikt kan worden waar een Base object gebruikt kan worden. Dat is dus ook bij het initialiseren van een nieuw Base object.

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...

Verwijderd schreef op zondag 09 juni 2013 @ 20:21:
Pas wel op met de construct uit de topicstart. Als je dat doet treed er een effect op wat slicing heet, base is dan mogelijk niet meer terug te dynamic_casten naar derived.
Dit :) niet doen zo.

  • MSalters
  • Registratie: Juni 2001
  • Laatst online: 13-09 00:05
Is dat niet vanzelfsprekend? Je kunt een Base object nooit dynamic_casten naar een Derived. Een pointer naar een Base object kun je wel naar een Derived pointer dynamic_casten. Dat kan wel, omdat de Base pointer ook naar een Derived object kan wijzen.

Objecten in C++ veranderen nooit van type. Het type staat vast op het moment dat ze gemaakt zijn. Datzelfde geldt voor hun locatie in geheugen. (this pointer), die verandert ook nooit. Zet je dus een Base object op de stack, dan blijft het een Base object op de stack.

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


Verwijderd

deze stackoverflow vraag beschrijft hoe je een object kan creëren wat zowel delen van Base als Derived bevat.

  • ThomasG
  • Registratie: Juni 2006
  • Laatst online: 18:54
Verwijderd schreef op dinsdag 11 juni 2013 @ 18:07:
deze stackoverflow vraag beschrijft hoe je een object kan creëren wat zowel delen van Base als Derived bevat.
Wat ook gelijk bad practise is. Je converteert immers niets voor niets van Derived naar Base. Als je dat doet is het schijnbaar niet nodig om de rest te gebruiken. Het zelfde als je naar een (pseudo-)interface zou casten. Als hij Derived wilt behouden, moet hij maar met bijvoorbeeld een template gaan werken.

De "oplossing" die op stackoverflow staat mag dan wel werken, maar hiermee krijg je enorme code vervuiling. Zoals de assignment op een reference :r.
Pagina: 1