Partilhar via


Classes de valor e estruturas (C++/CX)

Um value struct ou value class é um POD ("plain old data structure") compatível com o Tempo de Execução do Windows. Tem um tamanho fixo e consiste apenas em campos; ao contrário de uma classe ref, não tem propriedades.

Os exemplos a seguir mostram como declarar e inicializar estruturas de valor.

// in mainpage.xaml.h:
    value struct TestStruct
    {
        Platform::String^ str;
        int i;
    };

    value struct TestStruct2
    {
        TestStruct ts;
        Platform::String^ str;
        int i;
    };

// in mainpage.cpp:
    // Initialize a value struct with an int and String
    TestStruct ts = {"I am a TestStruct", 1};

    // Initialize a value struct that contains
    // another value struct, an int and a String
    TestStruct2 ts2 = {{"I am a TestStruct", 1}, "I am a TestStruct2", 2};

    // Initialize value struct members individually.
    TestStruct ts3;
    ts3.i = 108;
    ts3.str = "Another way to init a value struct.";

Quando uma variável de um tipo de valor é atribuída a outra variável, o valor é copiado, de modo que cada uma das duas variáveis tenha sua própria cópia dos dados. Um valor struct é uma estrutura de tamanho fixo que contém apenas campos de dados públicos e é declarada usando a palavra-chave value struct.

Uma classe de valor é como um value struct exceto que seus campos devem receber explicitamente acessibilidade pública. É declarado usando a palavra-chave value class.

Uma estrutura de valor ou classe de valor pode conter como campos apenas tipos numéricos fundamentais, classes de enumeração, Platform::String^ou Platform::IBox <T>^, onde T é um tipo numérico, classe de enumeração, classe de valor ou estrutura. Um campo IBox<T>^ pode ter um valor de nullptr—é assim que o C++ implementa o conceito de tipos de valor anuláveis.

Uma classe de valor ou estrutura de valor que contém um tipo Platform::String^ ou IBox<T>^ como membro não é memcpy-able.

Como todos os membros de um value class ou value struct são públicos e são emitidos em metadados, os tipos C++ padrão não são permitidos como membros. Isso é diferente das classes ref, que podem conter private ou internal tipos C++ padrão.

O fragmento de código a seguir declara os tipos Coordinates e City como estruturas de valor. Note que um dos membros de dados do City é do tipo GeoCoordinates. Um value struct pode conter outras estruturas de valor como membros.

public enum class Continent 
{  
    Africa,
    Asia,
    Australia,
    Europe,
    NorthAmerica,
    SouthAmerica,
    Antarctica 
};

value struct GeoCoordinates
{
    double Latitude; //or float64 if you prefer
    double Longitude;
};

value struct City
{
    Platform::String^ Name;
    int Population;
    double AverageTemperature;
    GeoCoordinates Coordinates;
    Continent continent;
};

Passagem de parâmetros para tipos de valor

Se você tiver um tipo de valor como um parâmetro de função ou método, ele normalmente é passado por valor. Para objetos maiores, isso pode causar um problema de desempenho. No Visual Studio 2013 e anteriores, os tipos de valor em C++/CX sempre eram passados por valor. No Visual Studio 2015 e posterior, você pode passar tipos de valor por referência ou por valor.

Para declarar um parâmetro que passa um valor tipo por valor, use um código como o seguinte:

void Method1(MyValueType obj);

Para declarar um parâmetro que passa um tipo de valor por referência, use o símbolo de referência (&), como a seguir:

void Method2(MyValueType& obj);

O tipo dentro de Method2 é uma referência a MyValueType e funciona da mesma maneira que um tipo de referência em C++ padrão.

Quando você chama Method1 de outra linguagem, como C#, você não precisa usar o ref ou out palavra-chave. Quando chamar o Method2, use a chave ref.

Method2(ref obj);

Você também pode usar um símbolo de ponteiro (*) para passar um tipo de valor por referência. O comportamento em relação aos chamadores em outros idiomas é o mesmo (chamadores em C# usam a palavra-chave ref), mas no método, o tipo é um ponteiro para o tipo de valor.

Tipos de valor anulável

Como mencionado anteriormente, uma classe de valor ou estrutura de valor pode ter um campo do tipo Platform::IBox<T>^—por exemplo, IBox<int>^. Esse campo pode ter qualquer valor numérico que seja válido para o tipo int ou pode ter um valor de nullptr. Você pode passar um campo anulável como um argumento para um método cujo parâmetro é declarado como opcional ou em qualquer outro lugar em que um tipo de valor não seja necessário para ter um valor.

O exemplo a seguir mostra como inicializar uma struct que tem um campo anulável.

public value struct Student
{
    Platform::String^ Name;
    int EnrollmentYear;
    Platform::IBox<int>^ GraduationYear; // Null if not yet graduated.
};
//To create a Student struct, one must populate the nullable type.
MainPage::MainPage()
{
    InitializeComponent();

    Student A;
    A.Name = "Alice";
    A.EnrollmentYear = 2008;
    A.GraduationYear = ref new Platform::Box<int>(2012);

    Student B;
    B.Name = "Bob";
    B.EnrollmentYear = 2011;
    B.GraduationYear = nullptr;

    IsCurrentlyEnrolled(A);
    IsCurrentlyEnrolled(B);
}
bool MainPage::IsCurrentlyEnrolled(Student s)
{
    if (s.GraduationYear == nullptr)
    {
        return true;
    }
    return false;
}

Uma estrutura de valor em si pode ser anulável da mesma forma, como mostrado aqui:

public value struct MyStruct
{
public:
    int i;
    Platform::String^ s;
};

public ref class MyClass sealed
{
public:
    property Platform::IBox<MyStruct>^ myNullableStruct;
};

Ver também

Tipo de Sistema (C++/CX)
Referência da linguagem C++/CX
Referência de Namespaces
classes e estruturas Ref (C++/CX)