Referenční třídy a struktury (C++/CX)

C++/CX podporuje uživatelem definované ref třídy a struktury ref a uživatelsky definované třídy hodnot a struktury hodnot. Tyto datové struktury jsou primární kontejnery, podle kterých C++/CX podporuje systém typů prostředí Windows Runtime. Jejich obsah se odesílá do metadat podle určitých specifických pravidel a umožňuje jejich předávání mezi komponentami prostředí Windows Runtime a aplikacemi Univerzální platforma Windows, které jsou napsané v jazyce C++ nebo jiných jazycích.

Třída ref nebo struktura ref má tyto základní funkce:

  • Musí být deklarován v rámci oboru názvů, v oboru názvů a v daném oboru názvů může mít veřejný nebo privátní přístupnost. Metadata se generují pouze veřejné typy. Definice vnořených veřejných tříd nejsou povoleny, včetně vnořených veřejných výčtových tříd. Další informace naleznete v tématu Obory názvů a viditelnost typů.

  • Může obsahovat jako členy C++/CX včetně tříd ref, hodnotových tříd, struktur ref, struktur hodnot nebo struktur hodnot s možnou hodnotou null. Může také obsahovat skalární typy, například float64, boola tak dále. Může také obsahovat standardní typy C++, jako std::vector je nebo vlastní třída, pokud nejsou veřejné. Konstrukty jazyka C++/CX mohou obsahovat public, protected, internal, private, nebo protected private přístupnost. Metadata se vygenerují všichni public členové nebo protected členové. Standardní typy jazyka C++ musí mít private, internalnebo protected private přístupnost, což brání jejich vygenerování do metadat.

  • Může implementovat jednu nebo více tříd rozhraní nebo struktury rozhraní.

  • Může dědit z jedné základní třídy a samotné základní třídy mají další omezení. Dědičnost v hierarchiích veřejných ref tříd má více omezení než dědičnost v privátních třídách ref.

  • Nemusí být deklarována jako obecná. Pokud má privátní přístupnost, může se jednat o šablonu.

  • Jeho životnost se spravuje automatickým počítáním odkazů.

Deklarace

Následující fragment kódu deklaruje Person třídu ref. Všimněte si, že standardní typ C++ std::map se používá v privátních členech a rozhraní prostředí Windows Runtime IMapView se používá ve veřejném rozhraní. Všimněte si také, že ^je připojen k deklaracím odkazových typů.

// #include <map>
namespace WFC = Windows::Foundation::Collections;
namespace WFM = Windows::Foundation::Metadata;

[WFM::WebHostHidden]
ref class Person sealed
{
public:
    Person(Platform::String^ name);
    void AddPhoneNumber(Platform::String^ type, Platform::String^ number);
    property WFC::IMapView<Platform::String^, Platform::String^>^ PhoneNumbers
    { 
        WFC::IMapView<Platform::String^, Platform::String^>^ get();
    }
private:
    Platform::String^ m_name;
    std::map<Platform::String^, Platform::String^> m_numbers;
};

Implementace

Tento příklad kódu ukazuje implementaci Person ref třídy:

#include <collection.h>
using namespace Windows::Foundation::Collections;
using namespace Platform;
using namespace Platform::Collections;

Person::Person(String^ name): m_name(name) { }
void Person::AddPhoneNumber(String^ type, String^ number)
{
    m_numbers[type] = number;
}
IMapView< String^, String^>^ Person::PhoneNumbers::get()
{
    // Simple implementation. 
    return ref new MapView< String^, String^>(m_numbers);
}

Využití

Následující příklad kódu ukazuje, jak klientský kód používá Person třídu ref.

using namespace Platform;

Person^ p = ref new Person("Clark Kent");
p->AddPhoneNumber("Home", "425-555-4567");
p->AddPhoneNumber("Work", "206-555-9999");
String^ workphone = p->PhoneNumbers->Lookup("Work");

K deklaraci proměnné místní třídy ref můžete použít také sémantiku zásobníku. Takový objekt se chová jako proměnná založená na zásobníku, i když je paměť stále přidělována dynamicky. Jedním z důležitých rozdílů je, že nemůžete přiřadit sledovací odkaz (%) proměnné, která je deklarována pomocí sémantiky zásobníku; to zaručuje, že při ukončení funkce se počet odkazů sníží na nulu. Tento příklad ukazuje základní třídu Uriref a funkci, která ji používá sémantikou zásobníku:

void DoSomething()
{
    Windows::Foundation::Uri docs("http://docs.microsoft.com");
    Windows::Foundation::Uri^ devCenter = docs.CombineUri("/windows/");
    // ... 
} // both variables cleaned up here.

Správa paměti

Přidělíte třídu ref v dynamické paměti pomocí klíčového ref new slova.

MyRefClass^ myClass = ref new MyRefClass();

Operátor handle-to-object ^ se označuje jako klobouk a je základním inteligentním ukazatelem jazyka C++. Paměť, na které odkazuje, je automaticky zničena, když poslední klobouk zmizí z rozsahu nebo je explicitně nastaven na nullptr.

Podle definice má třída ref referenční sémantiku. Když přiřadíte proměnnou třídy ref, jedná se o zkopírovaný popisovač, nikoli samotný objekt. V dalším příkladu po přiřazení nasměrujte oba myClass a myClass2 nasměrujte na stejné umístění paměti.

MyRefClass^ myClass = ref new MyRefClass();
MyRefClass^ myClass2 = myClass;

Při vytvoření instance třídy ref C++/CX je jeho paměť inicializována nulou před zavolání jeho konstruktoru; proto není nutné inicializovat jednotlivé členy, včetně vlastností. Pokud je třída C++/CX odvozená z třídy prostředí Windows Runtime knihovny C++ (WRL), je inicializována pouze část odvozené třídy C++/CX.

Členové

Ref třída může obsahovat public, protecteda private členy funkce; pouze public a protected členy jsou generovány do metadat. Vnořené třídy a třídy ref jsou povoleny, ale nemohou být public. Veřejná pole nejsou povolena; veřejné datové členy musí být deklarovány jako vlastnosti. Soukromé nebo chráněné interní datové členy mohou být pole. Ve výchozím nastavení ve třídě ref je privatepřístupnost všech členů .

Struktura ref je stejná jako třída ref, s tím rozdílem, že její členové mají public ve výchozím nastavení přístupnost.

Třída public ref nebo struktura ref se v metadatech vygeneruje, ale aby byla použitelná z jiných Univerzální platforma Windows aplikací a prostředí Windows Runtime komponent, musí mít alespoň jeden veřejný nebo chráněný konstruktor. Veřejná ref třída, která má veřejný konstruktor, musí být také deklarována, aby sealed se zabránilo další odvození prostřednictvím binárního rozhraní aplikace (ABI).

Veřejné členy nemusí být deklarovány, protože const systém typů prostředí Windows Runtime nepodporuje const. Statickou vlastnost můžete použít k deklaraci veřejného datového členu s konstantní hodnotou.

Když definujete veřejnou třídu ref nebo strukturu, kompilátor použije požadované atributy třídy a uloží tyto informace do souboru .winmd aplikace. Pokud však definujete veřejnou nezapečetěnou ref třídu, ručně použijte Windows::Foundation::Metadata::WebHostHidden atribut, aby se zajistilo, že třída není viditelná pro Univerzální platforma Windows aplikace, které jsou napsané v JavaScriptu.

Ref třída může mít standardní typy C++, včetně const typů, v libovolné private, internalnebo protected private členy.

Veřejné ref třídy, které mají parametry typu, nejsou povoleny. Uživatelem definované obecné referenční třídy nejsou povoleny. Soukromá, interní nebo chráněná soukromá třída ref může být šablona.

Destruktory

V jazyce C++/CX vyvolá volání delete veřejného destruktoru destruktor bez ohledu na počet odkazů objektu. Toto chování umožňuje definovat destruktor, který provádí vlastní vyčištění jiných prostředků než RAII deterministickým způsobem. I v tomto případě se však samotný objekt z paměti neodstraní. Paměť objektu je uvolněna pouze v případě, že počet odkazů dosáhne nuly.

Pokud destruktor třídy není veřejný, vyvolá se pouze v případě, že počet odkazů dosáhne nuly. Pokud zavoláte delete objekt, který má privátní destruktor, kompilátor vyvolá upozornění C4493, což říká, že výraz delete nemá žádný vliv, protože destruktor <názvu> typu nemá "veřejný" přístupnost."

Destruktory třídy Ref lze deklarovat pouze takto:

  • veřejné a virtuální (povolené u zapečetěných nebo nezapečetěných typů)

  • chráněné privátní i ne virtuální (povolené pouze u nezapečetěných typů)

  • private and non-virtual (allowed only on sealed types)

Není povolená žádná jiná kombinace přístupnosti, virtuální a zapečetěnosti. Pokud destruktor explicitně deklarujete, kompilátor vygeneruje veřejný virtuální destruktor, pokud základní třída typu nebo jakýkoli člen má veřejný destruktor. V opačném případě kompilátor generuje chráněný privátní ne-virtuální destruktor pro nezapečetěné typy nebo privátní ne-virtuální destruktor pro zapečetěné typy.

Chování není definováno, pokud se pokusíte získat přístup k členům třídy, která již měla jeho destruktor spuštění; s největší pravděpodobností způsobí chybové ukončení programu. Volání delete t typu, který nemá žádný veřejný destruktor, nemá žádný vliv. Volání delete this typu nebo základní třídy, která má známý private nebo protected private destruktor z jeho hierarchie typů, nemá žádný vliv.

Když deklarujete veřejný destruktor, kompilátor vygeneruje kód tak, aby ref třída implementuje Platform::IDisposable a destruktor implementuje metodu Dispose . Platform::IDisposableje projekce jazyka C++/CX .Windows::Foundation::IClosable Nikdy explicitně neimplementujte tato rozhraní.

Dědičnost

Platform::Object je univerzální základní třída pro všechny třídy ref. Všechny třídy ref jsou implicitně konvertibilní na Platform::Object a mohou přepsat Object::ToString. Model dědičnosti prostředí Windows Runtime však není zamýšlený jako obecný model dědičnosti. V jazyce C++/CX to znamená, že uživatelsky definovaná veřejná třída ref nemůže sloužit jako základní třída.

Pokud vytváříte uživatelský ovládací prvek XAML a objekt se účastní systému vlastností závislostí, můžete použít Windows::UI::Xaml::DependencyObject jako základní třídu.

Po definování nezapečetěné třídy MyBase , která dědí z DependencyObject, jiné veřejné nebo soukromé ref třídy ve vaší komponentě nebo aplikaci mohou dědit z MyBase. Dědičnost ve veřejných třídách ref by měla být provedena pouze pro podporu přepsání virtuálních metod, polymorfní identity a zapouzdření.

Privátní základní ref třída není nutná k odvození z existující nezapečetěné třídy. Pokud potřebujete hierarchii objektů k modelování vlastní struktury programu nebo k povolení opětovného použití kódu, použijte privátní nebo interní třídy ref nebo ještě lépe standardní třídy jazyka C++. Funkce hierarchie privátních objektů můžete zveřejnit prostřednictvím obálky veřejné zapečetěné třídy ref.

Ref třída, která má veřejný nebo chráněný konstruktor v C++/CX musí být deklarována jako zapečetěná. Toto omezení znamená, že neexistuje způsob, jak třídy napsané v jiných jazycích, jako je C# nebo Visual Basic, dědit z typů, které deklarujete v prostředí Windows Runtime komponentě napsané v jazyce C++/CX.

Tady jsou základní pravidla dědičnosti v jazyce C++/CX:

  • Třídy ref mohou dědit přímo z jedné základní ref třídy, ale mohou implementovat libovolný počet rozhraní.

  • Pokud třída má veřejný konstruktor, musí být deklarována jako zapečetěná, aby se zabránilo další odvození.

  • Můžete vytvořit veřejné nezapečetěné základní třídy, které mají interní nebo chráněné soukromé konstruktory za předpokladu, že základní třída je odvozena přímo nebo nepřímo z existující nezapečetěné základní třídy, jako Windows::UI::Xaml::DependencyObjectje například . Dědičnost uživatelem definovaných tříd ref v souborech .winmd není podporována; Ale ref třída může dědit z rozhraní, které je definováno v jiném souboru .winmd. Odvozené třídy můžete vytvořit z uživatelem definované základní ref třídy pouze ve stejné prostředí Windows Runtime komponentě nebo Univerzální platforma Windows aplikaci.

  • U tříd ref se podporuje pouze veřejná dědičnost.

    ref class C{};
    public ref class D : private C //Error C3628
    {};
    

Následující příklad ukazuje, jak zveřejnit veřejnou třídu ref, která je odvozena z jiných tříd ref v hierarchii dědičnosti.

namespace InheritanceTest2 
{
    namespace WFM = Windows::Foundation::Metadata;

    // Base class. No public constructor.
    [WFM::WebHostHidden]
    public ref class Base : Windows::UI::Xaml::DependencyObject
    {
    internal:
        Base(){}
    protected:
        virtual void DoSomething (){}
        property Windows::UI::Xaml::DependencyProperty^ WidthProperty;
    };

    // Class intended for use by client code across ABI.
    // Declared as sealed with public constructor.
    public ref class MyPublicClass sealed : Base
    {
    public:
        MyPublicClass(){}
        //...
    };
}

Viz také

Systém typů
Hodnotové třídy a struktury
Referenční zdroje k jazyku C++/CX
Referenční informace o oborech názvů