Virtuální základní třídy
Protože třída může být více než jednou nepřímé základní třídy odvozené třídy, C++ poskytuje způsob, jak optimalizovat způsob, jakým tyto základní třídy práce.Virtuální základní třídy představují způsob, jak ušetřit místo a zabránit dvojznačnosti v hierarchie tříd, které používají více dědičnosti.
Každý objekt nonvirtual obsahuje kopii dat členů definovaných ve třídě base.Tato duplikace zabírají místo a vyžaduje zadání kopii členy základní třídy, má vždy, když k nim přístup.
Při základní třídy je virtuální základní ji může fungovat jako nepřímé base více než jednou bez duplikace dat členů.Základní třídy, které používají virtuální základní sdílejí jednu kopii dat členů.
Při deklarování virtuální základní třídy virtuální klíčové slovo se zobrazí v základní seznamy odvozené třídy.
Zvažte hierarchie třídy na následujícím obrázku znázorňuje řádek simulované oběd.
Simulované oběd spojnicový
Obrázek Queue je základní třída pro oba CashierQueue a LunchQueue.Však při kombinaci obou tříd do formuláře LunchCashierQueue, vznikne následující problém: Nová třída obsahuje dvě podřízeným objektům typu Queue, jeden z CashierQueue a druhý z LunchQueue.Následující obrázek ukazuje koncepční paměti rozložení (rozložení skutečné paměti může být optimalizována).
Simulované oběd řádek objektu
Poznámka: jsou dvě Queue v subobjects LunchCashierQueue objektu.Následující kód deklaruje Queue být virtuální základní třída:
// deriv_VirtualBaseClasses.cpp
// compile with: /LD
class Queue {};
class CashierQueue : virtual public Queue {};
class LunchQueue : virtual public Queue {};
class LunchCashierQueue : public LunchQueue, public CashierQueue {};
virtual Klíčové slovo zajišťuje, že pouze jednu kopii určitých podřízených objektů Queue je součástí (viz následující obrázek).
Simulované objekt řádku oběd s virtuální základní třídy
Třída může mít virtuální komponenty a nonvirtual komponenty daného typu.Tato situace nastane v podmínkách, znázorněný na následujícím obrázku.
Virtuální a Nonvirtual součástí stejné třídy.
Obrázek CashierQueue a LunchQueue pomocí Queue jako virtuální základní třídy.Však TakeoutQueue Určuje Queue jako základní třída není virtuální základní třídy.Proto LunchTakeoutCashierQueue má dvě podřízeným objektům typu Queue: jedna z dědičnosti cesty, která zahrnuje LunchCashierQueue a jeden z cesty, která zahrnuje TakeoutQueue.Tento postup je znázorněn na následujícím obrázku.
Rozložení objektu s dědičností virtuální a Nonvirtual
[!POZNÁMKA]
Virtuální dědění poskytuje značné velikosti dávky ve srovnání s nonvirtual dědičnosti.Lze však zavádět dodatečné zatížení.
Pokud odvozená třída potlačí virtuální funkci, která zdědí virtuální základní třídy a konstruktor nebo destruktoru pro základní třídy odvozené volání funkce pomocí ukazatele virtuální základní třídy, kompilátor zavést další skryté "vtordisp" pole do tříd s virtuální základů.Volba kompilátoru /vd0 potlačuje přidání člena skryté vtordisp konstruktor/destruktoru přestavění.Volba kompilátoru /vd1, výchozí, umožňuje jim, kde jsou nezbytné.Vypněte vtordisps, pouze pokud jste si jisti, že všechny konstruktory tříd a destruktory volání funkce virtuální prakticky.
Volba kompilátoru /vd ovlivňuje modulu celé kompilace.Použití vtordisp pragma potlačit a potom znovu povolit vtordisp pole na základě třídy podle třídy:
#pragma vtordisp( off )
class GetReal : virtual public { ... };
#pragma vtordisp( on )