На этом шаге мы рассмотрим структуры native и managed.
Наряду с обычными классами и структурами (их еще называют native-классы и native-структуры), существуют классы и структуры для работы в среде Common Language Runtime (CLR, Общеязыковая среда выполнения) (их еще называют managed-классы и managed-структуры). Эти конструкции будут располагаться в выделенной средой CLR памяти и поэтому приложения с применением этого типа должны компилироваться с ключом /clr. Напомним, что в версии среды VC++ 2010 консольные приложения строятся по шаблону сразу с ключом /clr.
Приложения типа Windows Form этому условию удовлетворяют (мы их рассмотрим позже). Няпомним также, что объекты, попадающие в память под управлением CLR, требуют в программе специального выделения памяти, так как они должны попасть на самом деле в динамическую память. Мы уже знаем, что указатели на такую управляемую память обозначаются символом "^". Выделяют такую память с помощью утилиты gcnew.
Структуры и классы для работы в режиме CLR могут быть ссылочного типа (перед именем класса или структуры стоит квалификатор ref) и типа значения (перед именем класса или структуры стоит квалификатор value). В объявлении такой конструкиции первым квалификатором идет квалификатор доступа к данной конструкции. Для класса по умолчанию идет квалификат private, а для структуры - public, что также имеет место и для эквивалентов этих конструкций в режиме native (это - для предыдущих версий среды). В чем смысл этих конструкций?
Например, возьмем классы:
ref class MyClass { public: int m_i; }; value class MyClassV { public: int m_i; };
Это обычные классы, только атрибут ref указывает, что его класс надо размещать в управляемой куче.
Например:
MyClass ^mc = gcnew MyClass();
Если же попробовать его разместить в native-куче, то компилятор выдаст ошибку. А для класса с атрибутом value компилятор разрешает это делать, т. е. оператор:
MyClassV *vv = new MyClassV();
void main() { MyClass ^mc = gcnew MyClass();//идет //MyClass *mc = new MyClass();//не идет mc->m_i = 111; //присвоили значение члену класса int mci = mc->m_i; //достали значение из класса //MyClassV ^vv = gcnew MyClassV(); //не идет MyClassV *vv = new MyClassV(); //идет vv->m_i = 222; int mv = vv->m_i; Console::WriteLine("mci = " + mci + " mv= " + mv); delete vv; Console::ReadLine(); //задержка }
Результат работы приложения:
Рис.1. Результат работы приложения
Оказывается, что можно ссылаться из managed-типа на native-тип. Например, функция в managed-типе (классе или структуре) может принимать native-параметр (например, struct). При этом если managed-тип и функция имеют атрибут доступа public, то и native-тип должен иметь атрибут public.
Например:
// 79_2.cpp: главный файл проекта. #include "stdafx.h" using namespace System; //native-тип public struct N { int i; }; public ref struct R //managed-тип { // функция, у которой параметр nn имеет native-тип N int f(N nn) { nn.i++; return nn.i; } }; void main() { R ^r = gcnew R; N n; n.i = 333; int ni = r->f(n); Console::WriteLine("ni=" + ni); Console::ReadLine(); }
Результат работы приложения:
Рис.2. Результат работы приложения
На следующем шаге мы рассмотрим массивы в C++.