Архитектура Аудит Военная наука Иностранные языки Медицина Металлургия Метрология Образование Политология Производство Психология Стандартизация Технологии |
Список инициализации конструктора. Статические данные и функции
Если среди элементов - данных класса имеются константы, то инициализировать их можно только в конструкторе, причем для этой цели используется список инициализации конструктора (задается в конструкторе после двоеточия): class C1{ private: int var; const a; public: C1(int v, int c): a(c) { var = v; } };
Отметим, что список инициализации конструктора, использование которого обязательно для констант, ссылок и данных абстрактных типов (объектов), может быть использован и для " обычных" элементов класса, например:
class C1{ private: int var; const a; public: C1(int v, int c): a(c), var(v) {} };
Мы можем переписать конструктор копии для стека символов с использованием списка инициализации:
stack:: stack(const stack& str): max_len(str.max_len), top(str.top) { s = new char[str.max_len]; memcpy(s, str.s, max_len); }
Язык C++ позволяет объявлять элементы класса (данные и функции) как статические. Для любого класса может быть создана только одна копия статического элемента данных, причем память под статические элементы данных резервируется при запуске программы до создания объектов класса. Статическое поле данных не может быть инициализировано при описании класса или внутри функции. Следующий пример иллюстрирует использование статических элементов данных:
class s{ static sm; public: void show() { cout< < " static: " < < sm< < endl; } }; int s:: sm=10; void main() { // int s:: sm=5; // ошибка s s1; s1.show(); }
Объявление функционального элемента класса как статического означает, что к такой функции можно обратиться до того, как в программе будет создан первый объект класса. Статические функции используются не только для доступа к статическим элементам данных класса, но и для переопределения операций выделения и освобождения динамической памяти. На рис.8 приведена программа Fstatic.cpp, иллюстрирующая возможные варианты синтаксиса обращений к статическим функциональным элементам класса.
#include < iostream> using namespace std; class C1{ private: int numb; static int stat; public: C1(int i) { numb = i; } static void func (int i, C1* ptr = 0) { if(ptr) ptr-> numb=i; else stat = i; } static void show_s(void) { cout< < " stat=" < < stat< < endl; } };
int C1:: stat = 5; void main() { C1:: show_s(); C1:: func(10); C1 obj(15); obj.show_s(); C1:: func(20, & obj); obj.func(18, & obj); obj.show_s(); }
Рис.8. Программа Fstatic.cpp
Управляемые и неуправляемые типы языка С++ платформы.NET Управляемый (контролируемый) код – понятие, введенное разработчиками платформы.NET. Компилятор любого языка, поддерживаемого платформой.NET, создает байт-код (управляемый код) программы, который с одной стороны еще не привязан ни к какой аппаратной платформе, а с другой стороны не содержит в себе никаких особенностей, определяемых языком программирования. Для текстового (визуального) представления байт-кода разработан язык IL (Intermediate Language, промежуточный язык Microsoft), своеобразный ассемблер.NET байт-кода. Выполнение байт-кода на конкретной аппаратной платформе производится посредством одновременного преобразования его в код конкретного процессора с помощью виртуальной машины.NET, входящей в состав общеязыковой среды исполнения (Common Language Runtime, CLR). Именно виртуальная машина, называемая также JIT-компилятором (JIT - Just-in-Time, в процессе исполнения), работающая в среде CLR, гарантирует безопасное и контролируемое выполнение программы. Язык С++ - единственный язык платформы.NET, компилятор которого позволяет создавать как управляемый (managed) код для его последующего выполнения в среде CLR, так и неуправляемый (unmanaged) код, являющийся машинным кодом конкретного процессора. Естественно, что неуправляемый код выполняется быстрее байт-кода, но он менее безопасен (разрешается работать с указателями), не является мобильным, при выполнении не контролируется средой CLR. Объекты управляемого кода всегда создаются в динамической памяти (точнее, в управляемой динамически распределяемой области памяти, называемой кучей). Такие управляемые объекты создаются в программе с помощью оператора new, а удаляются специальной программой среды CLR, называемой сборщиком мусора GC (garbage collection, сборка мусора). В программе на С++ могут одновременно создаваться как управляемые объекты (классы таких объектов объявляются с ключевым словом __gc), так и неуправляемые объекты, для классов которых используется объявление __nogc. Поскольку в С++ класс и тип являются эквивалентными понятиями, то очевидными становятся такие понятия, как управляемые и неуправляемые типы. Управляемый тип – тип, для которого сборка мусора осуществляется автоматически и для освобождения ресурсов, используемых объектами этого типа, не требуется использовать оператор delete. Вместо того чтобы явно удалять управляемый объект, можно либо сделать так, чтобы на него не указывал ни один указатель, либо явно приравнять этот указатель нулю. На рис. 9 приведена простейшая управляемая программа на языке С++. При создании проекта управляемой программы необходимо указывать тип программы - CLR. Кроме этого, необходимо с помощью директивы using подключать библиотеку mscorlib.dll, которая делает доступными для компилятора стандартные типы (такие, как Console и Object).
#using < mscorlib.dll> //required by managed C++ code void main(void) { System:: Console:: WriteLine(" Hello World" ); }
Рис.9. Программа HelloWorld.cpp
Программа может иметь и управляемые и неуправляемые части кода (рис. 10).
#using < mscorlib.dll> #include < stdio.h> // Директива компилятору на генерацию неуправляемого кода. #pragma unmanaged // Эта функция будет неуправляемой, она будет транслирована // в чистый машинный код. void UnmanagedFunction() { printf(" Hello, World, from UnmanadegFunction! \n" ); } // Директива компилятору генерировать управляемый код. #pragma managed // Это управляемая функция, она будет транслирована в набор инструкций //.NET байт-кода. void ManagedFunction() { System:: Console:: WriteLine(S" Hello, World, from ManagedFunction! " ); UnmanagedFunction(); } // Эта функция также будет управляемой. void main() { ManagedFunction(); } Рис.10. Программа Some.cpp
Класс String платформы.NET Объект класса System:: String инкапсулирует (скрывает внутри объектной оболочки или обертки) строку символов Unicode (типа __wchar_t *). Тип String представляет собой конечный (sealed) класс; это означает, что он не может быть базовым для другого класса. Сам класс String – производный от класса System:: Object, являющегося основой иерархии классов платформы.NET. Объект класса String является неизменяемым (константным), т.е. будучи однажды инициализированным, он не может быть изменен. Класс String содержит методы, которые можно использовать для изменения объекта, такие как Insert, Replace, PadLeft. Однако эти методы только возвращают измененный объект, не изменяя сам объект, для которого они вызываются. В отличие от String методы класса StringBuilder позволяют изменять сам объект. В программе на рис. 11 показано, что метод Replace не влияет на содержимое исходного объекта класса String, но изменяет содержимое объекта класса StringBuilder.
#using < mscorlib.dll> using namespace System; //for Console and String using namespace System:: Text; //for StringBuilder
void main(void) { Console:: WriteLine(" String is immutable: " ); String *ps1 = S" Hello World"; String *ps2 = ps1-> Replace('H', 'J'); Console:: WriteLine(ps1); Console:: WriteLine(ps2); Console:: WriteLine(" StringBuilder can be modified: " ); StringBuilder *psb1 = new StringBuilder(S" Hello World" ); StringBuilder *psb2 = psb1-> Replace('H', 'J'); Console:: WriteLine(psb1); Console:: WriteLine(psb2); char *ps3 = " ASCII string literal"; // неуправляемый объект __wchar_t *ps4 = L" Unicode string literal"; // неуправляемый объект String *ps5 = S" String object literal"; // управляемый объект Console:: WriteLine(ps3); Console:: WriteLine(ps4); Console:: WriteLine(ps5); }
Рис.11. Программа StringReplace.cpp
В программе StringReplace используются строковые литералы (константы), определенные с префиксом S и без него. Строковый литерал, определенный с использованием только кавычек, является указателем на char (типом char*), т.е. указателем на последовательность символов ASCII, заканчивающуюся нулем. А строковый литерал, определенный с префиксом S, является указателем на управляемый объект класса String. Префикс L обозначает строку символов Unicode, имеющую тип __wchar_t *, которая также не является объектом класса String. Отметим, что · операционные системы MS Windows 9x работают с ASCII (с однобайтовой кодировкой) и не поддерживают Unicode – двухбайтовую кодировку символов; · существует технология компонентных объектов на базе платформы Win32 API (технология COM – Component Object Model), в которой строковые объекты инкапсулируют как строки ASCII, так и строки Unicode; тип этих объектов – BSTR (Basic STRing); · существуют библиотеки различных сред разработки (например, библиотеки VCL, MFC), в которых имеются классы строковых объектов, обычно инкапсулирующие строки ASCII. При работе со строковыми объектами необходимо различать операции сравнения указателей на объекты и операции сравнения самих объектов. В классе String метод Equals используется для сравнения содержания строковых объектов, заданных указателями (поскольку Equals является методом, т.е. member-функцией, сравниваемые объекты задаются this-указателем и указателем, переданным в Equals через явный аргумент). Операция == для указателей будет проверять только равенство адресов в указателях. В программе на рис. 12 представлены различные варианты сравнения строковых объектов и указателей на объекты.
#using < mscorlib.dll> using namespace System;
void main(void) { String *pstr1; String *pstr2; //comparing literal String objects pstr1 = S" hello"; pstr2 = S" hello"; if (pstr1-> Equals(pstr2)) Console:: WriteLine(" equal" ); //executed else Console:: WriteLine(" not equal" ); //not executed if (pstr1==pstr2) Console:: WriteLine(" equal" ); // executed else Console:: WriteLine(" not equal" ); //not executed //comparing new String objects (non literal) pstr1 = new String(" hello" ); pstr2 = new String(" hello" ); if (pstr1-> Equals(pstr2)) Console:: WriteLine(" equal" ); // executed else Console:: WriteLine(" not equal" ); //not executed if (pstr1==pstr2) Console:: WriteLine(" equal" ); //not executed else Console:: WriteLine(" not equal" ); //executed }
Рис.12. Программа StringLiteral.cpp
Управляемые строковые литералы String и неуправляемые строковые литералы ASCII и Unicode (благодаря автоматической упаковке) можно использовать в выражениях, в которых ожидается использование управляемого строкового объекта String. Однако управляемый строковый объект String нельзя использовать там, где ожидается появление переменных неуправляемых типов. В программе на рис. 13 представлены примеры допустимых и недопустимых преобразований типов для аргументов функций.
#using < mscorlib.dll> using namespace System; #include < wchar.h> //for wchar_t
void ExpectingManagedString(String *str){} void ExpectingASCIIString(char *str){} void ExpectingUnicodeString(wchar_t *str){}
void main(void) { //expecting a managed type ExpectingManagedString(S" hello" ); // совпадение типов ExpectingManagedString(" hello" ); // автоматическое преобразование ExpectingManagedString(L" hello" ); // автоматическое преобразование
//expecting an unmanaged type ExpectingASCIIString(" hello" ); // совпадение типов ExpectingASCIIString(S" hello" ); // ошибка! ExpectingUnicodeString(L" hello" ); // совпадение типов ExpectingUnicodeString(S" hello" ); // ошибка! }
Рис.13. Программа MixingStringTypes.cpp
Класс Array платформы.NET Обычные массивы являются простым типом указателя, например, int* (или, соответственно, int[]). Управляемые массивы являются управляемыми объектами, расположенными в динамически распределяемой области памяти. System:: Array – абстрактный класс, являющийся базовым для всех управляемых массивов. Для определения управляемого массива следует использовать либо ключевое слово __gc, либо указывать, что элементы массива относятся к управляемому типу. В программе на рис. 14 представлены различные способы объявления массивов. Отметим, что неуправляемые данные можно создавать как в стековой, так и в динамически распределяемой области памяти. Обратите внимание на две закомментированные строки в программе, в которых при объявлении массива задается его размер. Размер массива при объявлении можно задавать только для неуправляемого массива, который располагается в стеке, но нельзя задавать для управляемого массива, поскольку он располагается в динамической памяти и эта память при объявлении еще не выделяется (размер будет указан при выделении памяти с помощью оператора new).
#using < mscorlib.dll> using namespace System; // уничтожить предупреждение о переменной, на которую нет ссылки #pragma warning(disable: 4101) void main(void) { // синтаксис традиционного неуправляемого массива int *pintUnanagedArrayOnHeap = new int [5]; int intUnManagedArray[5]; //нет ошибки для unmanaged array
// синтаксис управляемого массива, используется __gc int intManagedArrayOnHeap __gc[] = new int __gc[5]; //int intManagedArray __gc[5]; //ошибка для managed array
// синтаксис управляемого массива, используется // управляемый тип элементов String *strManagedArrayOnHeap[] = new String*[5]; //String *strManagedArray[5]; //ошибка для managed array }
Рис.14. Программа ArraySyntax.cpp
Управляемые массивы наследуют от класса System:: Array методы Copy, GetLength, GetType и от класса System:: Object методы ToString и Eguals. Управляемые массивы, в отличие от неуправляемых (неконтролируемых) являются безопасными. При попытке доступа к элементу управляемого массива производится проверка принадлежности к диапазону индексов, т.е. контроль границ. При обращении по недопустимому индексу возникает исключение IndexOutOfRangeException. В программе на рис. 15 показано, как можно использовать обработчик исключений при попытке доступа к несуществующему элементу управляемого массива. Обратите внимание, что массив содержит пять элементов, а в цикле производится попытка установить значение шестого. Программа в обычном С++ выполнила бы такое действие, изменив содержимое памяти за пределами массива.
#using < mscorlib.dll> using namespace System;
void main () { int intArray __gc[]= new int __gc[5]; for (int i=0; i< 6; i++) // неправильная граница цикла!!! { try { intArray[i] = i; } catch (IndexOutOfRangeException *piore) { // здесь надо сделать что-то для исправления ошибки Console:: WriteLine(" Oooops! " ); Console:: WriteLine(piore-> get_Message()); } } }
Рис.15. Программа IndexOutOfRangeException.cpp
Как и для неуправляемых массивов, нумерация элементов в управляемых массивах начинается с нуля. Однако, в отличие от неуправляемых массивов, элементы управляемого массива автоматически инициализируются значением, принятым по умолчанию для каждого типа элемента массива. Переменным примитивных типов, таких, как int, char, float, double присваивается нуль. Элементам, указывающим на управляемые объекты, также по умолчанию присваивается нулевое значение (т.е. нулевой указатель). Элементы значимых типов (например, структур) инициализируются с помощью их принятого по умолчанию конструктора (т.е. конструктора, не имеющего аргументов для инициализации). Программа на рис. 16 иллюстрирует работу с массивами. В ней сравниваются двумерные массивы – управляемый и неуправляемый. Отметим, что синтаксис [, ] предполагает истинно прямоугольный массив, в то время как в синтаксисе [][] каждый подмассив может иметь разный размер (т.н. массив с неровным правым краем). Назначение закомментированных строк будет приведено в следующем подразделе.
#using < mscorlib.dll> using namespace System;
void main () { //managed 1D array of int (using __gc) Console:: WriteLine(" managed 1D array of int" ); int intArray __gc[]= new int __gc[5]; // array< int> ^ intArray = gcnew array< int> (5); for (int i=0; i< intArray-> Length; i++) { intArray[i] = i; Console:: Write(intArray[i]); Console:: Write(" \t" ); } Console:: WriteLine();
//managed 2D array of Strings (using managed type) Console:: WriteLine(" managed 2D array of Strings" ); String *str2DArray[, ] = new String *[2, 3]; // array< String^, 2> ^ str2DArray = gcnew array< String^, 2> (2, 3); for(int row=0; row< str2DArray-> GetLength(0); row++) { for(int col=0; col< str2DArray-> GetLength(1); col++) { str2DArray[row, col] = (row*10 + col).ToString(); Console:: Write(str2DArray[row, col]); Console:: Write(" \t" ); } Console:: WriteLine(); }
//unmanaged 2D array of int (for comparison) Console:: WriteLine(" unmanaged 2D array of int" ); int int2DArray[2][3]; for(int row=0; row< 2; row++) { for(int col=0; col< 3; col++) { int2DArray[row][col] = row*10 + col; Console:: Write(int2DArray[row][col]); Console:: Write(" \t" ); } Console:: WriteLine(); } }
Рис.16. Программа Array1.cpp
В программе Array1 управляемый прямоугольный двумерный массив содержит эленты типа String*, а неуправляемый – элементы типа int. Однако управляемый массив может также содержать и элементы неуправляемых типов, между тем как неуправляемый массив – лишь элементы неуправляемых типов. В программе на рис. 17 сравнивается использование массива массивов (синтаксис [][]) и прямоугольного двумерного массива (синтаксис [, ]). Для более корректного сравнения оба массива содержат элементы типа int.
#using < mscorlib.dll> using namespace System;
void main(void) { Console:: WriteLine(" Rectangular array using [, ]" ); int rect2DArray [, ] = new int __gc [3, 4]; //managed // array< int, 2> ^ rect2DArray = gcnew array< int, 2> (3, 4); for(int row=0; row< rect2DArray -> GetLength(0); row++) { for(int col=0; col< rect2DArray-> GetLength(1); col++) { rect2DArray [row, col] = row*10 + col; Console:: Write(rect2DArray[row, col]); Console:: Write(" \t" ); } Console:: WriteLine(); }
Console:: WriteLine(" Array of arrays using [][]" ); int arrayOfArray[3][4]; //unmanaged for(int row=0; row< 3; row++) { for(int col=0; col< 4; col++) { arrayOfArray[row][col] = row*10 + col; Console:: Write(arrayOfArray[row][col]); Console:: Write(" \t" ); } Console:: WriteLine(); } }
Рис.17. Программа Array2.cpp
Язык Visual C++ 2005 Язык Visual С++ фирмы Microsoft основывается на трех стандартах: ISO C 95, ISO C++ 98 и Ecma C++/CLI 05. Управляемый (Managed) Visual С++, входящий в состав Visual Studio 2003 (MC++ 2003 в дальнейшем) значительно изменился в новой редакции, которая входит в Visual Studio 2005, т.е. в MC++ 2005. Поэтому в проекте приложения, использующего старую версию управляемого языка С++, необходимо использовать опцию компилятора /clr: oldSyntax. Опция /clr определяет использование новой редакции языка С++. Синтаксис языка MC++ 2005 соответствует спецификации C++/CLI (Common Language Infrastructure, Общеязыковая Инфраструктура). Он заменяет старый синтаксис языка MC++ 2003, известный как Managed Extensions for C++. Наиболее полная информация об этих языках представлена в документации MSDN. Для обращения к ней необходимо выбрать опцию Contents в меню Help (или нажать кнопку Contents), установить в окне Contents фильтр Visual C++, а затем выбрать следующую последовательность опций: Development Tools and Languages -> Visual Studio -> Visual C++ -> Getting Started -> How Do I in Visual C++ -> C++ Language -> Managed Extensions for C++ Syntax Upgrade Checklist (или опции Development Tools and Languages -> Visual Studio -> Visual C++ -> Getting Started -> Reference -> C/C++ Language -> C++ Language Reference -> New C++ Language Features). В окне просмотра документации целесообразно установить фильтр для языков программирования: Language Filter -> C++. В С++ 2005 появились ключевые слова, состоящие из двух слов, разделенных пробелом, например ref class (класс, используемый в библиотеках DLL). Некоторые из новых возможностей пришли в MC++ 2005 из языка C#, который в области объектно-ориентированного программирования имеет значительно больше возможностей, а также из библиотеки STL (Standard Template Library) языка С++, имеющей богатые возможности по использованию шаблонов классов и функций. На рис. 18 приведен пример программы на языке MC++ 2005, в которой функция Test1() создает и инициализирует управляемый массив целых чисел, а затем этот массив возвращается как значение функции Test1().
// Test1.cpp // compile with: /clr using namespace System;
#define ARRAY_SIZE 10
// Returns a managed array of Int32. array< Int32> ^ Test1() { int i; array< Int32 > ^ local = gcnew array< Int32 > (ARRAY_SIZE);
for (i = 0; i < ARRAY_SIZE; i++) local[i] = i + 10; return local; } int main() { int i;
// Declares an array of value types and initializes with a function. array< Int32 > ^ IntArray; IntArray = Test1();
for (i = 0; i < ARRAY_SIZE; i++) Console:: WriteLine(" IntArray[{0}] = {1}", i, IntArray[i]); Console:: WriteLine(); }
Рис.18. Пример программа на языке MC++ 2005
Для того, чтобы программы Array1.cpp и Array2.cpp перевести с синтаксиса MC++ 2003 на синтаксис MC++ 2005, достаточно заменить строки объявления массивов с использованием __gc на строки с ключевым словом array (на рис. 16 и 17 эти строки закомментированы).
ОБОРУДОВАНИЕ Персональный компьютер: процессор с частотой 1, 6ГГц или выше, 1024 МБ ОЗУ, жесткий диск со скоростью 5400 об/мин, видеоадаптер с поддержкой DirectX 9 и с разрешением 1280 х 1024 (или более высоким), операционная система MS Windows 7, интегрированные среды разработки приложений Visual Studio 2010 и Visual Studio Team System 2008 с комплектами документации MSDN, каталог Tprog\Lab2, содержащий файл Labtprog4.doc (методические указания к данной лабораторной работе) и исходные файлы Stack1.h, Stack1.cpp, Stack2.h, Stack2.cpp, Str.h, Str.cpp, Strprog.cpp, Fstatic.cpp, HelloWorld.cpp, Some.cpp, StringReplace.cpp, StringLiteral.cpp, MixingStringTypes.cpp, ArraySyntax.cpp, IndexOutOfRangeException.cpp, Array1.cpp, Array2.cpp, не менее 200 Mб свободной памяти на логическом диске, содержащем каталог Tprog\Lab2.
ЗАДАНИЕ НА РАБОТУ
4.1. Ознакомиться с технологией создания и отладки объектно-ориентированных программ на управляемом (managed) и неуправляемом (unmanaged) языке С++ в интегрированной среде разработки приложений Visual Studio 2010 в процессе создания приложений Stack1, Stack2, Strprog, Fstatic, HelloWorld, Some, StringReplace, StringLiteral, MixingStringTypes, ArraySyntax, IndexOutOfRangeException, Array1, Array2, Test1, Array1_05, Array2_05. 4.2. Разработать и отладить объектно-ориентированную программу на управляемом (managed) и неуправляемом (unmanaged) языке С++ в интегрированной среде разработки приложений Visual Studio 2010 в соответствии с заданием преподавателя. Примерами заданий могут быть следующие:
Complex x(1.3, 4.2), y(4.0, 8.1), z(y); z.assign(plus(x, y)); print(plus(y, z));
Complex x(1.3, 4.2), y(4.0, 8.1), z(y); x.add(y); z.assign(plus(x, y)); z.print();
Point p1(10, 20), p2(40, 25), p3; p3.assign(p2); p3.mul(2); (move(p2, 40, 20)).print();
Point p1(10, 20), p2(40, 25), p3(p1); assign(p1, p2); mul(p3, 2); print(p2.(move(40, 20));
Circle c1(1, 1, 5), c2; assign(c2, (c1.mul(5))); c2.move(10, 20); resize(c1, 10, 20, 30); c1.print();
ПОРЯДОК ВЫПОЛНЕНИЯ РАБОТЫ
5.1. Проверить наличие на компьютере необходимого аппаратного оборудования и программного обеспечения, наличие 200 Мб свободной памяти на логическом диске, содержащем каталог Tprog\Lab2, наличие файла Labtprog2.doc и исходных файлов Stack1.h, Stack1.cpp, Stack2.h, Stack2.cpp, Str.h, Str.cpp, Strprog.cpp, Fstatic.cpp, HelloWorld.cpp, Some.cpp, StringReplace.cpp, StringLiteral.cpp, MixingStringTypes.cpp, ArraySyntax.cpp, IndexOutOfRangeException.cpp, Array1.cpp, Array2.cpp, Test1.cpp, Array1_05.cpp, Array2_05.cpp в каталоге Tprog\Lab2. 5.2. Создать личный каталог, в котором будут размещаться создаваемые во время лабораторной работы проекты. 5.3. Создать в личном каталоге пустой проект неуправляемого консольного приложения, выбирая в IDE-среде в меню File следующую последовательность опций: New-> Project-> Other Language -> Visual C++ -> Win32 -> Win32 Console Application -> Empty Project, а затем добавить в него файлы Stack1.h и Stack1.cpp, предварительно выполнив копирование в каталог проекта исходных файлов приложения. По команде Ctrl+F5 откомпилировать проект и выполнить приложение. Проверить правильность работы приложения. 5.4. Повторить выполнение пункта 5.3 для приложений Stack2, Strprog, Fstatic. Для смены файлов в проекте необходимо в окне Solution Explorer удалить файлы проекта из разделов Header Files и Source Files (выбирая в контекстном меню Exclude From Project), а затем добавить в эти разделы файлы нового приложения (выбирая в контекстном меню Add -> Existing Item). 5.5. Создать в личном каталоге пустой проект управляемого консольного приложения, выбирая в IDE-среде в меню File следующую последовательность опций: New-> Project-> Other Language -> Visual C++ -> CLR -> CLR Empty Project, а затем добавить в него файл HelloWorld.cpp, предварительно выполнив копирование в файл проекта исходных файлов приложения. Установить свойство проекта – запись операторов программы в старом стиле. Для этого перед компиляцией проекта необходимо выделить имя проекта в окне Solution Explorer и выбрать в меню Project последовательность опций: Properties-> Configuration Properties -> General -> Common Language Runtime support -> Common Language Runtime Support, Old Syntax (/clr: oldSyntax) -> OK. По команде Ctrl+F5 откомпилировать проект и выполнить приложение. Проверить правильность работы приложения. 5.6. Повторить выполнение пункта 5.4 для приложений Some, StringReplace, StringLiteral, MixingStringTypes, ArraySyntax, IndexOutOfRangeException, Array1, Array2. Для смены файлов в проекте необходимо в окне Solution Explorer удалить файлы проекта из разделов Header Files и Source Files (выбирая в контекстном меню Exclude From Project), а затем добавить в эти разделы файлы нового приложения (выбирая в контекстном меню Add -> Existing Item). 5.7. Создать в личном каталоге пустой проект управляемого консольного приложения, выбирая в IDE-среде в меню File следующую последовательность опций: New-> Project-> Other Language -> Visual C++ -> CLR -> CLR Empty Project, а затем добавить в него файл Test1.cpp, предварительно выполнив копирование в файл проекта исходных файлов приложения. Проверить свойство проекта – запись операторов программы в новом стиле. Для этого перед компиляцией проекта необходимо выделить имя проекта в окне Solution Explorer и выбрать в меню Project последовательность опций: Properties-> Configuration Properties -> General -> Common Language Runtime support -> Common Language Runtime Support (/clr) -> OK. По команде Ctrl+F5 откомпилировать проект и выполнить приложение. Проверить правильность работы приложения. 5.8. Повторить выполнение пункта 5.4 для приложений Array1_05, Array2_05. Для смены файлов в проекте необходимо в окне Solution Explorer удалить файлы проекта из разделов Header Files и Source Files (выбирая в контекстном меню Exclude From Project), а затем добавить в эти разделы файлы нового приложения (выбирая в контекстном меню Add -> Existing Item). 5.9. Разработать и отладить объектно-ориентированную программу на управляемом (managed) и неуправляемом (unmanaged) языке С++ в интегрированной среде разработки приложений Visual Studio 2010 в соответствии с заданием преподавателя. Если при отладке возникают проблемы с устранением ошибок в программе, необходимо выделить ошибку в окне Error List и нажать клавишу F1. В появившемся окне документации MSDN будет приведены примеры исправления ошибки.
ОФОРМЛЕНИЕ ОТЧЕТА
Отчет должен содержать: · цель работы и индивидуальное задание; · тексты исходных файлов, содержащие описание и реализацию классов, используемых в лабораторной работе; · файлы *.h и *.cpp, содержащие описание и реализацию классов в соответствии с заданием преподавателя; · текст тестовой программы и результаты работы программы; · краткая информация о создании управляемых программ и данных.
КОНТРОЛЬНЫЕ ВОПРОСЫ
7.1. В чем преимущества объектно-ориентированной реализации абстрактного типа stack перед процедурной реализацией? 7.2. Какие действия может выполнять конструктор? 7.3. К каким разделам класса имеет доступ функция main программы? 7.4. В каких случаях в классы вводят деструкторы? 7.5.В каких случаях используется конструктор копии? 7.6. Какой конструктор называется конструктором по умолчанию? Его основное назначение? 7.7. Данные каких типов необходимо инициализировать с помощью списка инициализации конструктора? 7.8. Как используются статические элементы класса? 7.9.Какие объекты называются управляемыми? Как их создать? 7.10.Какие строковые литералы используются в управляемых программах? 7.11. Можно ли использовать неуправляемые строковые литералы ASCII и Unicode в выражениях, в которых ожидается использование управляемого строкового объекта String? 7.12. Можно ли задавать размер массива при объявлении управляемого массива? 7.13. От каких базовых классов и какие методы наследуют управляемые массивы? 7.14. Как инициализируются управляемые массивы при создании?
БИБЛИОГРАФИЧЕСКИЙ СПИСОК
1. Оберг Р. Дж., Торстейнсон П. Архитектура.NET и программирование с помощью Visual C++. – М.: Издательский дом " Вильямс", 2002. – 656 с. 3. Троелсен Э. Язык программирования C# 2005 и платформа.NET 2.0. Библиотека программиста. 3-е изд. – М.: ООО «И.Д. Вильямс», 2007. – 1168 с. 3. Гарнаев А.Ю. Самоучитель Visual Studio.Net 2003. – СПб.: БХВ-Петербург, 2003. – 688 с. 4. Дубовцев А.В. Microsoft.NET в подлиннике. – СПб.: БХВ-Петербург, 2004. – 704 с. 5. Уоткинз Д., Хаммонд М., Эйбрамз Б. Программирование на платформе.NET. – М.: Издательский дом " Вильямс", 2003. – 368 с. 6. MSDN 2010. Электронная документация Microsoft для разработчиков программного обеспечения. – 500000 с.
ЛАБОРАТОРНАЯ РАБОТА N 3 Использование перегрузки операций при создании абстрактных типов на языке C++
ЦЕЛЬ И ЗАДАЧИ РАБОТЫ
Ознакомление с технологией создания абстрактного типа и перегрузки операций с использованием свойств, member- и friend-функций, а также получение практических навыков разработки и отладки объектно-ориентированных программ на языке С++ в интегрированной среде разработки приложений Visual Studio 2010.
ТЕОРЕТИЧЕСКИЕ СВЕДЕНИЯ
В языке С++ классы можно рассматривать как строительный материал и одновременно инструмент, с помощью которого программист создает свой тип данных, называемый абстрактным типом. Тип может быть создан с помощью одного класса или с помощью целой иерархии классов. Понятие " тип" включает в себя не только представление объекта, но и операции над таким объектом. Если тип реализуется посредством одного класса, то функции, объявленные в описании класса, определяют множество допустимых для данного типа операций. Эти функции подразделяются на функции-элементы класса (функциональные компоненты класса) и дружественные функции. Они имеют неограниченный доступ к элементам-данным класса и образуют интерфейс класса. Если элементы-данные обычно являются приватными, то функции интерфейса в большинстве случаев являются общедоступными, и только через функции интерфейса пользователь получает доступ к приватным (скрытым) элементам класса. В языке С++ по сравнению с языком С используется новый вид функций - операторные функции. Их назначение - дать возможность переопределить стандартные операторы языка С++ для новых (абстрактных) типов данных. Другими словами, операторные функции используются для перегрузки операций. При описании класса операторные функции могут быть объявлены как функции-элементы класса (member-функции) и как дружественные классу функции (friend-функции). Функции с результатом ссылочного типа Язык С++ предоставляет возможность использования ссылок при передаче аргументов и при получении результатов выполнения функции. Ссылки-аргументы функции позволяют не создавать локальные копии объектов-аргументов внутри функции, что особенно важно для объектов, содержащих большие массивы данных. Вызовы функции с результатом ссылочного типа являются именами переменных и, следовательно, могут использоваться с левой стороны операции присваивания. Однако в качестве возвращаемой переменной не должна использоваться локальная переменная, которая существует только внутри функции. В программе на рис.1 запись Set(Arr, 2) - это имя элемента Arr[2], которому присваивается значение 13. Функцию Set() можно использовать как слева, так и справа от оператора присваивания. В последнем случае имя переменной (адрес переменной) разыменовывается. Функцию Set1(), возвращающую значение, можно использовать только справа от оператора присваивания.
#include < iostream> using namespace std; int& Set(int *Vec, int index) { return Vec[index]; } int Set1(int *Vec, int index) { return Vec[index]; } /*int& Set2(void) { int a=1; return a; // ошибка } */ int Arr[]={10, 20, 30}; int main(void) { Set(Arr, 2)=13; cout< < Arr[2]< < endl; int b=Set(Arr, 1); int c=Set1(Arr, 2); cout< < b< < " " < < c< < endl; //Set2()=5; // ошибка return 0; }
Рис.1. Программа Refer.cpp
Популярное:
|
Последнее изменение этой страницы: 2016-05-03; Просмотров: 715; Нарушение авторского права страницы