Sdílet prostřednictvím


Převody

Objekt převodu vytváří novou hodnotu typu některé z hodnoty jiného typu.Standardní převody jsou integrovány do jazyka C++ a podporu, můžete vytvořit jeho vestavěné typy a uživatelem definované převody k provedení převodů na, z nebo mezi typy definované uživatelem.

Standardní převody provádět převody mezi vestavěné typy, mezi ukazatele nebo odkazy na typy související prostřednictvím dědičnosti do a z void ukazatele a na ukazatele null.Další informace naleznete v tématu Standardní převody.Uživatelem definované převody provádět převody mezi typy definované uživatelem, nebo uživatelem definované typy a vestavěné typy.Je možné implementovat jako převod konstruktory nebo jako funkcí pro převod.

Převody může být buď explicitní – když volá programátora pro jeden typ má být převeden do druhého, stejně jako v přetypování nebo přímé inicializace – nebo implicitní – Pokud jazyk nebo program vyžaduje, aby jiného typu než je dáno programátora.

Implicitní převody jsou aplikovány při:

  • Argument přidělená funkci nemá stejný typ jako odpovídající parametru.

  • Hodnota vrácená z funkce nemá stejný typ jako návratový typ funkce.

  • Výraz inicializátoru nemá stejný typ jako objekt, který je inicializace.

  • Výraz, který řídí podmíněný příkaz, konstrukci cyklu nebo přepínače nemá typ výsledku, který je požadováno nad ním kontrolu.

  • Operand poskytnutá pro operátor nemá stejný typ jako odpovídající operand parametr.Integrované operátory oba operandy musí být stejného typu a jsou převedeny na společný typ, který může představovat oba.Další informace naleznete v tématu Aritmetické převody.Pro operátory definované uživatelem musí mít každý operand stejného typu jako odpovídající operand parametr.

Když jeden standardní převod nelze dokončit implicitní převod, kompilátor můžete použít uživatelem definovaný převod, volitelně následovaný další standardní převod k jejímu dokončení.

Pokud dvě nebo více uživatelem definované převody, které stejný převod provést jsou k dispozici na webu převod, převod se říká být nejednoznačný.Takové nejasnosti jsou chybu, protože kompilátor nemůže určit, který z nich dostupné převody měli zvolit.Však není chybu pouze k definování více způsobů provádění stejný převod, protože sada dostupné převody mohou být různé na různých místech ve zdrojovém kódu – v závislosti na tom, jaké záhlaví například soubory jsou zahrnuty ve zdrojovém souboru.Dokud pouze jeden převodu je k dispozici na webu převod, nedochází k nejednoznačnosti.Existuje několik způsobů, které mohou vzniknout nejednoznačný převody, ale nejobvyklejší z nich jsou:

  • Více dědičnost.Převod je definován více než jeden základní třídy.Další informace naleznete v tématu Nejednoznačnost.

  • Volání funkce nejednoznačný.Převod je definován jako konstruktor převod cílového typu a jako funkci pro převod typu zdroje.Další informace naleznete v tématu funkcí pro převod.

Obvykle lze vyřešit nejednoznačnosti tak, že název typu zapojené více plně kvalifikované nebo provedením explicitní přetypování pro objasnění váš záměr.

Převod konstruktory a funkcí pro převod dodržovat pravidla pro řízení přístupu člena, ale přístupnost převody považován pouze pokud jednoznačné převod může být určen.To znamená, že převod může být nejednoznačný i v případě, že úroveň přístupu konkurenčních převodu by znemožnilo z používán.Další informace o usnadnění člena, naleznete v části Ovládací prvek přístupu členů.

Explicitní klíčové slovo a problémy s implicitní převod

Ve výchozím nastavení při vytváření uživatelem definovaný převod kompilátor slouží k provedení implicitní převody.V některých případech se jedná, co má, ale jiné časy jednoduchých pravidel, které provedou kompilátor při vytvoření implicitní převody může vést jí přijímat kód, který nechcete, aby ji.

Převod na je dobře známé příkladem implicitní převod, který může způsobit problémy s bool.Existuje mnoho důvodů, které chcete vytvořit typ třídy, kterou lze použít v kontextu typu Boolean – například tak dokáže lze použít k řízení if prohlášení nebo cyklu –, ale v případě, že kompilátor provádí uživatelem definovaný převod na předdefinovaný typ, kompilátor je povoleno použít později další standardního převodu.Záměr tento další standardní převod je umožnit řadí propagace z short k int, otevře také dveří pro převod na méně zřejmé, ale – například od bool k int, což umožňuje vašeho typu třída se používá v celé číslo kontexty nikdy určen.Tento určitý problém se označuje jako bezpečného Bool problém.Tento druh problému je tam, kde explicit může pomoci klíčové slovo.

explicit Klíčové slovo říká kompilátoru, že zadaný převod nelze použít k provedení implicitní převody.Pokud byste chtěli syntaktické pohodlí implicitní převody před explicit byla zavedena klíčové slovo, bylo nutné přijmout nežádoucí důsledky tohoto implicitní převod někdy vytvářeny nebo pomocí funkcí pro převod menší praktické, s názvem jako řešení.Nyní, a to s využitím explicit klíčové slovo, můžete vytvořit jediné převody, který lze použít pouze k provedení explicitní přetypování nebo přímé inicializace a která nevede k druh příklad bezpečného problémem Bool problémy.

explicit Klíčové slovo lze použít k převodu konstruktory od C ++ 98 a funkcí pro převod od C ++ 11.Následující oddíly obsahují další informace o tom, jak používat explicit klíčové slovo.

Převod konstruktory

Převod konstruktory definovat převod z uživatelem definované nebo vestavěné typy uživatelem definovaného typu.Následující příklad ukazuje převod konstruktor, který převádí z předdefinovaný typ double na typ uživatelem definované Money.

#include <iostream>

class Money
{
public:
    Money() : amount{ 0.0 } {};
    Money(double _amount) : amount{ _amount } {};

    double amount;
};

void display_balance(const Money balance)
{
    std::cout << "The balance is: " << balance.amount << std::endl;
}

int main(int argc, char* argv[])
{
    Money payable{ 79.99 };

    display_balance(payable);
    display_balance(49.95);
    display_balance(9.99f);

    return 0;
}

Oznámení, že první volání funkce display_balance, který přebírá argument typu Money, nevyžaduje převod, protože jeho argumentem je správného typu.Však na druhé volání display_balance, převod je vyžadován, protože typ argumentu, double s hodnotou 49,95, není co funkce očekává.Tuto hodnotu nelze použít přímo, funkce, ale vzhledem k tomu, že existuje převod z typu argument –double– na typ odpovídající parametru –Money– dočasných hodnoty typu Money je zkonstruován z argumentu a použít k dokončení volání funkce.Ve třetím volání display_balance, Všimněte si, že argument není double, místo toho, ale float s hodnotou 9.99– a ještě volání funkce lze stále dokončit, protože kompilátor můžete provést standardní převod – v takovém případě z float k double– a proveďte převod definovaný uživatelem z double k Money dokončete nezbytné převod.

Deklarující konstruktory převodu

Chcete-li deklarující konstruktor převod platí následující pravidla:

  • Cílový typ převodu je typ definovaný uživatelem, který je vytvářen.

  • Převod konstruktory obvykle provádějí přesně jeden argument, který je typu zdroje.Konstruktor převod však můžete zadat další parametry, pokud každý další parametr nemá výchozí hodnotu.Typ zdroje zůstane typ prvního parametru.

  • Převod konstruktory, jako jsou všechny konstruktory, nezadávejte návratovým typem.Určení návratový typ v deklaraci je k chybě.

  • Převod konstruktory, může být explicitní.

Explicitní převod konstruktory

Deklarací konstruktor převod být explicit, jej lze použít pouze k provedení přímé inicializace objektu nebo k provedení explicitní přetypování.Tím je zabráněno funkce, které přijmout argument typu třídy z také implicitně přijímá argumenty konstruktoru převodu typu zdroje a brání typu třídy kopírování inicializován z hodnoty typu zdroje.Následující příklad ukazuje, jak lze definovat explicitní převod konstruktor a efekt, který má o jaký kód je ve správném formátu.

#include <iostream>

class Money
{
public:
    Money() : amount{ 0.0 } {};
    explicit Money(double _amount) : amount{ _amount } {};

    double amount;
};

void display_balance(const Money balance)
{
    std::cout << "The balance is: " << balance.amount << std::endl;
}

int main(int argc, char* argv[])
{
    Money payable{ 79.99 };        // Legal: direct initialization is explicit.

    display_balance(payable);      // Legal: no conversion required
    display_balance(49.95);        // Error: no suitable conversion exists to convert from double to Money.
    display_balance((Money)9.99f); // Legal: explicit cast to Money

    return 0;
}

V tomto příkladu Všimněte si, že můžete konstruktoru explicitní převod nadále používat k provedení přímé inicializace payable.Pokud místo toho byly kopie inicializace Money payable = 79.99;, by bylo k chybě.První volání display_balance není ovlivněn, protože argument je správného typu.Druhé volání display_balance je chyba, protože konstruktor převod nelze použít k provedení implicitní převody.Třetí volání display_balance je právní z důvodu explicitní přetypování na Money, ale Všimněte si, že kompilátor stále přispěl k dokončení přetypování vložením implicitní přetypování z float k double.

Ačkoli pohodlí povolení implicitní převody mohou být tempting, učiníte tak může způsobovat pevný nalézt chyby.Pravidlem je, aby všechny konstruktory převod explicitní s výjimkou případů, kdy jste si jisti, má specifický převod neproběhne implicitně.

Funkce pro převod

Funkce pro převod definovat převody z uživatelem definovaného typu na jiné typy.Tyto funkce jsou někdy nazývá "přetypování operátory" vzhledem k tomu, že, spolu s převod konstruktory, jsou volány při hodnotu vložena do jiného typu.Následující příklad ukazuje funkci pro převod, který převádí z typ uživatelem definovaného Money, na předdefinovaný typ double:

#include <iostream>

class Money
{
public:
    Money() : amount{ 0.0 } {};
    Money(double _amount) : amount{ _amount } {};

    operator double() const { return amount; }
private:
    double amount;
};

void display_balance(const Money balance)
{
    std::cout << "The balance is: " << balance << std::endl;
}

Všimněte si, že členské proměnné amount je provedena soukromé a že veřejný převod fungovat na typ double je zavedena pouze má být vrácena hodnota amount.Ve funkci display_balance, implicitní převodu dochází, když hodnota balance je vysílán do standardního výstupu pomocí operátoru vložení datového proudu <<.Vzhledem k tomu, že je pro typ uživatelem definovaného definován žádný datový proud vložení operátor Money, je jedna pro předdefinovaný typ, ale double, kompilátor můžete použít funkci pro převod z Money k double vyhovět operátor vložení datového proudu.

Funkce pro převod jsou zděděna odvozené třídy.Funkce pro převod v odvozené třídě přepsat zděděné převod funkce pouze při převodu do stejného typu.Například funkce uživatelem definovaný převod odvozené třídy operator int nemůže přepsat – nebo dokonce vliv – uživatelem definovaný převod funkce základní třídy operator short, přestože standardní převody definovat převod vztah mezi int a short.

Funkce deklarující převodu

Chcete-li deklarující funkci pro převod platí následující pravidla:

  • Cílový typ převodu musí být deklarována před prohlášení o funkci pro převod.Třídy, struktury, výčtů a funkce TypeDef nemůže být deklarována v rámci prohlášení o funkci pro převod.

    operator struct String { char string_storage; }() // illegal
    
  • Funkce převodu nepřijímají argumenty.Zadání žádné parametry v deklaraci je chyba.

  • Funkce pro převod mají návratový typ, který je určen název funkci pro převod, což je také název cílového typu převodu.Určení návratový typ v deklaraci je k chybě.

  • Funkce pro převod může být virtuální.

  • Funkce pro převod může být explicitní.

Funkce explicitní převodu

Pokud funkci pro převod je deklarován jako explicitní, lze použít pouze k provedení explicitní přetypování.Tím je zabráněno funkce, které přijmout argument typu cíl funkci pro převod z také implicitně přijímá argumenty typu třídy a brání instance typu cíl kopírování inicializovat z hodnoty typu třídy.Následující příklad ukazuje, jak lze definovat explicitní převod funkce a účinek má na to, jaký kód je ve správném formátu.

#include <iostream>

class Money
{
public:
    Money() : amount{ 0.0 } {};
    Money(double _amount) : amount{ _amount } {};

    explicit operator double() const { return amount; }
private:
    double amount;
};

void display_balance(const Money balance)
{
    std::cout << "The balance is: " << (double)balance << std::endl;
}

Sem funkci pro převod operator double byla provedena explicitní a explicitní přetypování na typ double byla zavedena ve funkci display_balance k provedení převodu.Pokud toto přetypování byly vynechán, bude kompilátor nelze najít vhodný datový proud vložení operátor << pro typ Money a dojde k chybě.

Viz také

Referenční dokumentace

Speciální členské funkce (C++)