Шаг 80.
Microsoft Visual C++ 2010. Язык С/С++.
Классы, структуры и массивы в среде CLR. Массивы в C++

    На этом шаге мы рассмотрим еще один способ задания массивов.

    В языке C++ наряду с обычным объявлением массива в виде "тип Имя[размерность]" (native-массивы) можно объявить массив, пользуясь ключевым словом array (managed-массивы). Этот массив будет располагаться в выделенной средой CLR памяти.

    Синтаксис объявления такого массива следующий:

  [qualifiers] [cli::]array <[qualifiers]type1[, dimension]>^ var = gcnew 
    [cli::] array<type2[, dimension]>(val[,val...])

    Здесь:

    Квалификатор mutable, например, означает, что если массив имеет такой квалификатор и является членом класса, то ему может присваивать значения функция (тоже член класса), у которой есть квалификатор const. В объявлении массива этого типа присутствует утилита gcnew, которая сразу же в объявлении выделяет под экземпляр массива CLR-память.

    Пример работы с рассмотренным массивом приведен ниже, а результат - на рисунке 1. Пояснения к тексту программы даны в самом тексте.


   Примечание. Все что мы рассматривали ранее, касающееся структур, классов и массивов, не предназначенных для работы в среде CLR, намеренно сохрнено на тот случай, если пользователю придется обращаться к более ранним средам.
// 80_1.cpp: главный файл проекта.

#include "stdafx.h"

// compile with: /clr

using namespace System; //этот оператор подключается в заголовку
                        //автоматически, когда вы задаете CLR-шаблон 
                        //консольного приложения

#define ARRAY_SIZE 2
value struct MyStruct //managed-value-структура
{
	int m_i;
};
 
ref class MyClass // managed-ref-класс
{
	public:
		int m_i;
};

struct MyNativeClass //native-структура
{
	int m_i;
};

//Эта функция возвращает массив ссылочного типа (массив ссылок): 
array<MyClass^>^ Test0()  // <MyClass^> - тип массива: ссылки на объекты класса
{
	int i;
	//объявление массива с именем local[] (это массив ссылок на объекты класса):
	array<MyClass^>^ local = gcnew array<MyClass^>(ARRAY_SIZE); 
	for (i = 0; i < ARRAY_SIZE; i++)
	{
		//Для каждого элемента массива надо создать экземпляр класса MyClass, 
		//чтобы получить доступ к члену этого класса:
		local[i] = gcnew MyClass; //возвращает ссылку на выделенную память
		local[i]->m_i = i;      //члену экземпляра класса MyClass m_i
		                          //присваивается значение i 
	} 
	return local; //возвращается массив ссылок на созданные объекты класса
}
//Функция возвращает массив целых чисел типа Int32. 
array<Int32>^ Test1() //<Int32> - тип массива
{
	int i;
	//объявление массива с именем local[] (это массив ссылок на числа типа Int32):
	array<Int32>^ local = gcnew array<Int32>(ARRAY_SIZE);
	for (i = 0; i < ARRAY_SIZE; i++)
		local[i] = i + 10; 
	return local;
}
//Функция модифицирует массив, т.к. через указатели это можно 
//делать с внешними переменными:
void Test2 (array<MyNativeClass*>^ local)
{
	for (int i = 0; i < ARRAY_SIZE; i++)
		local[i]->m_i = local[i]->m_i + 2; 
}

void main()
{
	int i;
	//Объявляется массив MyClass() и инициализируется функцией TestO():
	//происходит присвоение значений одного массива значениям
	//другого массива, т. к. массивы идентичны по построению
	array<MyClass^>^ MyClass0; 
	MyClass0 = Test0();

	//Вывод значений массива на экран
	for (i = 0; i < ARRAY_SIZE; i++)
		Console::WriteLine("MyClass0[{0}] = {1}", i, MyClass0[i]->m_i);
	Console::WriteLine();

	//Объявляется массив чисел IntArray[] и инициализируется функцией Test1():
	array<Int32>^ IntArray; 
	IntArray = Test1(); 
	//Вывод значений массива на экран
	for (i = 0; i < ARRAY_SIZE; i++)
		Console::WriteLine("IntArray[{0}] = {1}", i, IntArray[i]); 
	Console::WriteLine();

	//Объявляется и инициализируется массив MyClass1:
	array<MyClass^>^ MyClass1 = gcnew array<MyClass^>(ARRAY_SIZE);
	for (i = 0; i < ARRAY_SIZE; i++)
	{
		MyClass1[i] = gcnew MyClass;
		MyClass1[i]->m_i = i + 20;
	}
	
	//Вывод значений массива на экран
	for (i = 0; i < ARRAY_SIZE; i++)
		Console::WriteLine("MyClass1[{0}] = {1}", i, MyClass1[i]->m_i); 
	Console::WriteLine();

	//Объявляется массив обычных указателей и инициализируется:
	array<MyNativeClass*>^ MyClass2 = 
            gcnew array<MyNativeClass*>(ARRAY_SIZE); 
	for (i = 0; i < ARRAY_SIZE; i++)
	{
		//Обратите внимание, что вместо утилиты gcnew применяется new, 
		//т. к. последняя утилита работает с нормальными указателями,
		//задаваемыми символами "*", 
		//a gcnew - с указателями среды CLR,  задаваемыми символом "^*"
		MyClass2[i] = new MyNativeClass(); 
		MyClass2[i]->m_i = i + 30;
	}
	//Вывод значений массива на экран
	for (i = 0; i < ARRAY_SIZE; i++)
		Console::WriteLine("MyClass2[{0}] = {1}", i, MyClass2[i]->m_i); 
	Console::WriteLine();

	//Модификация массива и вывод значений на экран
	Test2(MyClass2); 
	for (i = 0; i < ARRAY_SIZE; i++)
		Console::WriteLine("MyClass2[{0}] = {1}", i, MyClass2[i]->m_i);
	Console::WriteLine();

	//Удаление массивов после применения оператора new 
	//(среда CLR сама освобождает память):
	delete[] MyClass2[0];
	delete[] MyClass2[1];

	//Использование конструктора класса
	array<MyStruct>^ MyStruct1 = gcnew array<MyStruct>(ARRAY_SIZE); 
	for (i = 0; i < ARRAY_SIZE; i++)
	{
		//модификация элементов класса
		MyStruct1[i] = MyStruct(); 
		//Конструктор класса создает экземпляр класса 
		MyStruct1[i].m_i = i + 40;
	}
	//Вывод значений массива на экран
	for (i = 0; i < ARRAY_SIZE; i++)
		Console::WriteLine("MyStruct1[{0}] = {1}", i, MyStruct1[i].m_i);
		
	Console::ReadLine(); //для задержки экрана
}
Архив проекта можно взять здесь.

    Результат работы приложения:


Рис.1. Результат работы приложения

    Со следующего шага мы начнем рассматривать ввод и вывод в языках C и C++.




Предыдущий шаг Содержание Следующий шаг