Классы и структуры значений (C++/CX)
Структура значений или класс значений — это совместимый с среда выполнения Windows POD ("обычная старая структура данных"). Она имеет фиксированный размер и состоит только из полей только; в отличие от класса ссылки, у нее нет свойств.
В следующих примерах показано, как объявлять и инициализировать структуры значений.
// 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.";
Когда переменная типа значения присваивается другой переменной, значение копируется, так что каждая из двух переменных содержит собственную копию данных. Структура значения — это структура фиксированного размера, содержащая только открытые поля данных и объявляемая с помощью ключевого слова value struct
.
Класс значения похож на value struct
за тем исключением, что его поля должны быть явно объявлены открытыми. Он объявляется с помощью ключевого слова value class
.
Структуру значений или класс значений может содержать в виде полей только фундаментальные числовые типы, классы перечисления, Platform::String^
или Platform::IBox <T>^ , где T является числовым типом или классом перечисления или классом значений или структурой. Поле IBox<T>^
может иметь значение nullptr
; таким образом в C++ реализуется концепция типов значений, допускающих значения NULL.
Класс значения или структура значения, содержащие в качестве члена тип Platform::String^
или IBox<T>^
, не поддерживают memcpy
.
Поскольку все члены класса value class
или value struct
являются открытыми и передаются в метаданные, не разрешается использовать стандартные типы C++ в качестве членов. Это отличается от классов ссылок, которые могут содержать стандартные типы C++ private
или internal
.
В следующем фрагменте кода типы Coordinates
и City
объявляются как структуры значения. Обратите внимание, что один из членов данных класса City
принадлежит к типу GeoCoordinates
. value struct
может в качестве членов содержать другие структуры значений.
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;
};
Передача параметров для типов значений
Если параметром функции или метода является тип значения, он обычно передается по значению. Для больших объектов это может вызвать проблемы с производительностью. В Visual Studio 2013 и более ранних версиях типы значений в C++/CX всегда передаются по значению. В Visual Studio 2015 и последующих версиях типы значений можно передавать по значению или по ссылке.
Чтобы объявить параметр, который передает тип значения по значению, используйте код, аналогичный приведенному ниже:
void Method1(MyValueType obj);
Чтобы объявить параметр, который передает тип значения по ссылке, используйте символ ссылки (&), как показано в следующем примере:
void Method2(MyValueType& obj);
Тип в Method2 является ссылкой на MyValueType и работает так же, как ссылочный тип в стандартном C++.
При вызове Method1 из другого языка, например C#, не требуется использовать ключевое слово ref
или out
. При вызове Method2 используйте ключевое слово ref
.
Method2(ref obj);
Также можно использовать символ указателя (*) для передачи типа значения по ссылке. Поведение по отношению к вызывающим объектам в других языках совпадает (вызывающие объекты в C# используют ключевое слово ref
), но в методе тип является указателем на тип значения.
Типы значений, допускающие значение NULL
Как упоминалось ранее, класс значений или структуру значений может иметь поле типа Platform::IBox<T>^, например IBox<int>^
. Это поле может иметь любое числовое значение, допустимое для типа int
, или значение nullptr
. Поле, допускающее значение NULL, можно передать в качестве аргумента методу, параметр которого объявлен как необязательный, или в любой другой объект, в котором тип значения не обязательно должен иметь значение.
В следующем примере показано, каким образом выполняется инициализация структуры с полем, допускающим значение null.
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;
}
Саму структуру значений можно сделать допускающей значение null аналогичным образом, как показано в следующем примере.
public value struct MyStruct
{
public:
int i;
Platform::String^ s;
};
public ref class MyClass sealed
{
public:
property Platform::IBox<MyStruct>^ myNullableStruct;
};
См. также
Система типов (C++/CX)
Справочник по языку C++/CX
Справочник по пространствам имен
Классы и структуры ссылки (C++/CX)