2016-04-05 10 views
3

Wie meinen Compiler kommt nicht geben Sie mir eine Warnung oder einen Fehler für diesen Code:Referenztypen und Vererbung gibt

class A {}; 
class B : public A{}; 
class C : public A{}; 
int main(int argc,char** args) 
{ 
    B b; 
    A& a = b; 
    C c; 
    a = c; 
} 

Ich würde dazu neigen zu glauben, dass dies in den Daten führen würde, in dem „b gespeichert werden "Variable ist nicht mehr vom Typ" B "und wird mir eine Menge Probleme bereiten ... also warum kann ich das machen?

+0

google „C++ Slicing“ –

Antwort

1

a = c; führt Zuordnung zwischen dem A Teil b, und dem Teil der Ac. Die B und C Teile (falls vorhanden) dieser Objekte sind unverändert.

Im Allgemeinen ist das ungefährlich, da die Objekte B und C möglicherweise nicht so entworfen wurden, dass nur ihr A Unterobjekt zugewiesen wird. Auf this thread sind verschiedene andere Vorschläge für die Handhabung operator= in einer Klassenhierarchie.

+0

Also mit anderen Worten meines „b“ Variable sicher ist, aber mein „a“ Variable wird nicht wirklich so handeln, wie ich es erwarten würde? – DarthRubik

+1

@DarthRubik Nun, ich bin mir nicht sicher, wie Sie erwarten, dass das 'a' wirkt –

1

Siehe Anmerkungen:

class A {}; 
class B : public A{}; 
class C : public A{}; 
int main(int argc,char** args) 
{ 
    B b; // memory allocated for b to contain A+B 
    A& a = b; // a is referencing A part of A+B 
    C c; // memory allocated for c to contain A+C 
    a = c; // a (A part of A+B) is overwritten from A part of A+C, c is sliced into a 
} 

Hoffnung, das hilft.

1

Wieso gibt mir mein Compiler keine Warnung oder einen Fehler?

Eine Klasse hat einen Kopierkonstruktor und Zuweisungsoperator standardmäßig, wenn sie nicht explizit deklariert wurden. Daher kann eine Instanz der abgeleiteten Klasse (C) einer Variablen des Basisklassentyps (A) zugewiesen werden. Dieser Effekt ist bekannt als slicing.

aus Um dies zu verhindern, dass Sie Copykonstruktor und Zuweisungsoperator in der Basisklasse deaktivieren:

class A 
{ 
    protected: 
    A() = default; 
    A(const A & source) = delete; 
    A & operator = (const A & source) = delete; 
}; 

class B : public A{}; 
class C : public A{}; 


int main(int argc,char** args) 
{ 
    B b; 
    A& a = b; 
    C c; 
    a = c; // this will not compile 
}