Объектно-ориентированное программирование в С++

Содержание

Слайд 2

Объектно-ориентированное программирование
Идея классов является основой объектно-ориентированного программирования (ООП).
Класс является типом данных определяемым

Объектно-ориентированное программирование Идея классов является основой объектно-ориентированного программирования (ООП). Класс является типом
пользователем. В классе задаются свойства и поведение какого-либо предмета или процесса в виде полей данных (аналогично структуре) и функций для работы с ними (методов).

Слайд 3

Интерфейсом класса являются заголовки
его методов.
Конкретные величины типа данных «класс» называются экземплярами класса,

Интерфейсом класса являются заголовки его методов. Конкретные величины типа данных «класс» называются
или объектами.
Основными принципами ООП являются:
Инкапсуляция;
Наследование;
Полиморфизм.

Слайд 4

Описание класса
Класс является абстрактным типом данных, определяемым пользователем, и представляет собой модель

Описание класса Класс является абстрактным типом данных, определяемым пользователем, и представляет собой
реального объекта в виде данных и функций для работы с ними.
Данные класса называются полями (свойствами), а функции класса — методами. Поля и методы называются элементами класса.

Слайд 6

При описании класса реализуется одно из ключевых понятий ООП - инкапсуляция. Для

При описании класса реализуется одно из ключевых понятий ООП - инкапсуляция. Для
начала дадим формальное определение этого понятия:
Инкапсуляция - это механизм, который объединяет данные и методы, манипулирующие этими данными, и защищает и то и другое от внешнего вмешательства или неправильного использования.

Слайд 7

Описание класса выглядит так:
class <имя>{
[ private: ]
<описание скрытых элементов>
public:
<описание доступных элементов>
} ;
Где

Описание класса выглядит так: class { [ private: ] public: } ;
спецификаторы доступа private и publiс управляют видимостью элементов класса. Элементы, описанные после служебного слова private, видимы только внутри класса. Этот вид доступа принят в классе по умолчанию.

Слайд 8

Термин private понимается в том смысле, что данные заключены внутри класса и

Термин private понимается в том смысле, что данные заключены внутри класса и
защищены от несанкционированного доступа функций, расположенных вне класса. Такие данные доступны только внутри класса.
Данные, описанные ключевым словом publiс, напротив, доступны за пределами класса.

Слайд 10

Поля класса:
• могут иметь любой тип, кроме типа этого же класса (но

Поля класса: • могут иметь любой тип, кроме типа этого же класса
могут быть указателями или ссылками на этот класс);
• могут быть описаны с модификатором const, при этом они инициализируются только один раз (с помощью конструктора) и не могут изменяться.
Инициализация полей при описании не допускается.
Методы класса – это функции входящие в состав класса.

Слайд 11

Описание объектов
Конкретные переменные типа «класс» называются экземплярами класса, или объектами.
Время жизни

Описание объектов Конкретные переменные типа «класс» называются экземплярами класса, или объектами. Время
и видимость объектов зависит от вида и места их описания и подчиняется общим правилам С++.
Формат:
class <имя> переменная;
Замечание: Объект находится в таком же отношении к своему классу, в каком переменная находится по отношению к своему типу.

Слайд 12

Пример1.
Рассмотрим пример описания класса TPoint (точка):
Точка характеризуется координатами: Х и У –

Пример1. Рассмотрим пример описания класса TPoint (точка): Точка характеризуется координатами: Х и
это свойства объекта;
Над точкой можно выполнять следующие действия:
- можно задать её координаты;
- точку можно переместить (изменив координаты);
- можно получить(узнать) координаты точки.

Слайд 13

#include "stdafx.h "
class TPoint
{ private:
int x,y;
public:
void InitPoint ( int

#include "stdafx.h " class TPoint { private: int x,y; public: void InitPoint
newx, int newy)
{ x = newx; y = newy ; }
void relmove ( int dx, int dy )
{x+= dx; y += dy ; }
int getx ( void ) { return x ; }
int gety ( void ) { return y ; }
};

Слайд 14

int main()
{ class TPoint p;
p.InitPoint(10,10);
printf("x=%d, y=%d\n", p.getx(), p.gety());

int main() { class TPoint p; p.InitPoint(10,10); printf("x=%d, y=%d\n", p.getx(), p.gety()); p.relmove(5,10);
p.relmove(5,10);
printf("x=%d, y=%d\n", p.getx(), p.gety());
return 0;
}
В этом классе два скрытых поля — x и y, получить значения которых извне можно с помощью методов getx() и gety().
Все методы класса имеют непосредственный доступ к его скрытым полям.

Слайд 16

Классы могут быть глобальными (объявленными вне любого блока) и локальными (объявленными внутри

Классы могут быть глобальными (объявленными вне любого блока) и локальными (объявленными внутри
блока, например, функции или другого класса).
МЕТОДЫ КЛАССА
Вызов методов класса
При вызове методов необходимо связать метод с объектом этого класса. Поэтому имена объектов ( p ) связаны с именем функции (метода) операцией точка (.):
p.InitPoint(10,10); p.relmove(5,10);
Замечание: Это напоминает доступ к полям структуры.

Слайд 17

Вызов методов InitPoint() и relmove() приводило к изменению значений полей Х и

Вызов методов InitPoint() и relmove() приводило к изменению значений полей Х и
У. В следующем примере задание полей в методе Vvod() будет осуществляться с клавиатуры:
class TPoint
{ private: int x,y;
public:
void InitPoint ( int newx, int newy)
{ x = newx; y = newy ; }
void Vvod()
{printf("Vvedi X Y:");scanf("%d%d",&x,&y);}
. . . };
Тогда вызов этого метода будет: p.Vvod();

Слайд 18

Конструкторы
B отличии от предыдущего примера удобнее инициализировать поля объекта автоматически в момент

Конструкторы B отличии от предыдущего примера удобнее инициализировать поля объекта автоматически в
его создания, а не явно вызовом соответствующего метода. Такой способ реализуется с помощью особого метода класса, называемого конструктором.
Конструктор - это метод, выполняющийся автоматически в момент создания объекта.
Конструктор отличается от других методов:
Имя конструктора совпадает с именем класса;
2) У конструктора не существует возвращаемого значения.

Слайд 19

class TPoint
{ private:
int x,y;
public:
TPoint(int newx, int newy) // конструктор

class TPoint { private: int x,y; public: TPoint(int newx, int newy) //
{x=newx; y=newy; }
void relmove ( int dx, int dy )
{x+= dx; y += dy ; }
int getx ( void ) { return x ; }
int gety ( void ) { return y ; } };
int main(int argc, char *argv[])
{ class TPoint p(10,10); //инициализация объекта р
printf("x=%d, y=%d\n", p.getx(), p.gety());
…}

Слайд 20

Пример 2.
В качестве примера создадим класс Counter, объекты которого могут хранить количественную

Пример 2. В качестве примера создадим класс Counter, объекты которого могут хранить
меру какой-либо изменяющейся величины.
При наступлении некоторого события счетчик увеличивается на единицу. Обращение к счетчику происходит, как правило, для того, чтобы узнать текущее значение той величины, для изменения которой он предназначен.

Слайд 21

class Counter
{ private: int mycount;
public:
Counter ( ):mycount(0){ }//конструктор
void inc_count (

class Counter { private: int mycount; public: Counter ( ):mycount(0){ }//конструктор void
) {mycount++; } //метод
int get_count( ) { return mycount; } //метод
};
int _tmain(int argc, _TCHAR* argv[])
{ Counter c1, c2; //описание объектов класса
std::cout< std::cout< c1.inc_count(); c2.inc_count();
std::cout< std::cout< return 0;}

Слайд 22

Одной из наиболее часто возлагаемых на конструктор задач является инициализация полей объекта.

Одной из наиболее часто возлагаемых на конструктор задач является инициализация полей объекта.
Инициализация полей обычно реализуется с помощью списка инициализации, который располагается между заголовком и телом функции-конструктора. После заголовка ставится двоеточие. Инициализирующие значения помещены в круглые скобки после имени поля.
Counter ( ): mycount(0)
{/* тело функции*/ }
Если инициализируются несколько полей, то значения разделяются запятыми.

Слайд 23

Деструкторы
Кроме специального метода конструктор, который вызывается при создании объекта, существует другой особый

Деструкторы Кроме специального метода конструктор, который вызывается при создании объекта, существует другой
метод, автоматически вызываемый при уничтожении объекта, называемый деструктором.
Деструктор имеет имя, совпадающее с именем конструктора, перед которым стоит тильда ~.
class Prim
{ private: int dat;
public:
Prim(): dat(0)
{ }
~Prim()
{ }
};

Слайд 24

Наиболее распространённое применение деструкторов – освобождение памяти, выделенной конструктором при создании объекта.
Определение

Наиболее распространённое применение деструкторов – освобождение памяти, выделенной конструктором при создании объекта.
методов может быть реализовано как внутри самого класса, так и вне класса. Во втором случае внутри класса содержится лишь прототип функции, а сама функция определяется позже. Тогда перед именем функции указывается имя класса и символ ::

Слайд 25

class TPoint
{ private:
int x,y;
public:
TPoint(int newx, int newy)
{x=newx;y=newy; }
void

class TPoint { private: int x,y; public: TPoint(int newx, int newy) {x=newx;y=newy;
relmove ( int dx, int dy );
int getx ( void ) { return x ; }
int gety ( void ) { return y ; }
~Tpoint( ) { }
};
void TPoint::relmove(int dx, int dy)
{x+= dx; y += dy ; }

Слайд 26

ЗАМЕЧАНИЯ:
1)Класс может иметь несколько конструкторов с разными параметрами для разных видов инициализации.
2)Конструктор,

ЗАМЕЧАНИЯ: 1)Класс может иметь несколько конструкторов с разными параметрами для разных видов
вызываемый без параметров, называется конструктором по умолчанию.
3)Деструктор вызывается автоматически, когда объект выходит из области видимости:
• для локальных объектов — при выходе из блока, в котором они объявлены;
• для глобальных — как часть процедуры выхода из main( );
• для объектов, заданных через указатели деструктор вызывается неявно при использовании операции delete.

Слайд 27

Деструктор:
• не имеет аргументов и возвращаемого значения;
• не может быть объявлен как

Деструктор: • не имеет аргументов и возвращаемого значения; • не может быть
const или static;
• не наследуется;
• может быть виртуальным.
Вернемся к примеру 2, где был создан class Counter. При решении разных задач может возникнуть необходимость инициализации счетчика разными значениями, а не только нулем. Для этого создадим еще один конструктор.

Слайд 28

class Counter
{ private: int mycount;
public:
Counter ( ):mycount(0){ }
Counter (int c):

class Counter { private: int mycount; public: Counter ( ):mycount(0){ } Counter
mycount(c){ }
void inc_count ( ) {mycount++; }
int get_count( ) { return mycount; }
~Counter( ){} };
int _tmain(int argc, _TCHAR* argv[])
{ Counter c1, c2(3);
std::cout< std::cout< c1.inc_count(); c2.inc_count();
std::cout< std::cout<

Слайд 29

Наследование
Наследование – это процесс создания новых классов, называемых наследниками или производными классами,

Наследование Наследование – это процесс создания новых классов, называемых наследниками или производными
из уже существующих или базовых классов. Производный класс получает все возможности базового класса, но может быть усовершенствован за счет добавления собственных.
Наследование – важная часть ООП. Выигрыш от него состоит в том, что наследование позволяет использовать существующий код несколько раз.

Слайд 31

Простым называется наследование, при котором производный класс имеет одного родителя.
Формат описания производного

Простым называется наследование, при котором производный класс имеет одного родителя. Формат описания
класса:
В заголовке производного класса через двоеточие (:) указывается имя родительского класса.
сlass имя_класса :
<спецификатор доступа> имя_базоваго_класса
{
объявление элементов класса
};
При описании производного класса надо помнить, что поля и методы родительского класса могут быть унаследованы!!!

Слайд 32

Рассмотрим правила наследования различных методов:
Конструкторы не наследуются, поэтому производный класс должен иметь

Рассмотрим правила наследования различных методов: Конструкторы не наследуются, поэтому производный класс должен
собственные конструкторы.
Если в конструкторе производного класса явный вызов конструктора базового класса отсутствует, автоматически вызывается конструктор базового класса по умолчанию.
Деструкторы также не наследуются, и если программист не описал в производном классе деструктор, он формируется по умолчанию.
Остальные методы могут наследоваться или переопределяться.

Слайд 33

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

Поля, унаследованные из родительского класса, и которые определены в базовом классе как
private, недоступны функциям производного класса.
Если они должны использоваться функциями, определенными в производном классе, можно либо описать их в базовом классе как protected, либо явно переопределить их в производном классе.
Вернемся к примеру счетчиков. Предположим, что нам понадобился метод, уменьшающий значение счетчика. Разработаем новый класс CountDown.

Слайд 34

class Counter
{ protected: int mycount;
public:
Counter ( ):mycount(0){ } //конструктор 1
Counter(int c):

class Counter { protected: int mycount; public: Counter ( ):mycount(0){ } //конструктор
mycount(c){ } //конструктор 2
void inc_count ( ) {mycount++; }
int get_count( ) { return mycount; }
};

class CountDown: public Counter
{ public:
void dec_count ( )
{mycount--; }
};
Новый класс наследует: поле mycount и методы get_count( ) и inc_count().

Слайд 35

int main(int argc, char *argv[])
{ Counter c1, c2(3);
CountDown c3;
std::cout< std::cout<

int main(int argc, char *argv[]) { Counter c1, c2(3); CountDown c3; std::cout
std::cout< c1.inc_count(); c2.inc_count();
c3.dec_count();
std::cout< std::cout< std::cout< return 0;
}

Слайд 36

Для объекта c3 доступен новый метод: c3.dec_count();
Но можно применять и унаследованные методы,

Для объекта c3 доступен новый метод: c3.dec_count(); Но можно применять и унаследованные
например: std::cout<Можно добавить в программу еще две строчки:
c3.inc_count();
std::cout<<"!!!"<Тогда значение счетчика с3 увеличится!
Переменная с3 – это объект класса CountDown. В классе CountDown нет конструктора. Если в производном классе не определен конструктор, то используется конструктор базового класса без параметров.
Но мы не сможем воспользоваться конструктором с параметром из базового класса.

Слайд 37

Поэтому, если возникает необходимость инициализации объекта с3 каким-либо другим значением, мы должны

Поэтому, если возникает необходимость инициализации объекта с3 каким-либо другим значением, мы должны
написать новый конструктор:

class CountDown: public Counter //определение класса
{ public:
CountDown ( ):Counter(0){ }
CountDown(int c): Counter(c){ } //конструктор2
void dec_count ( ) {mycount--; }
};

Так как действия в конструкторах базового и производного классов совпадают, то мы подключаем вызов конструкторов базового класса, для выполнения нужных действий.

Слайд 38

Иерархия классов
На основе принципа наследования может быть построена иерархия классов.
Рассмотрим пример

Иерархия классов На основе принципа наследования может быть построена иерархия классов. Рассмотрим
базы данных служащих некоторой компании. В ней существует три категории служащих: менеджеры, занимающиеся продажами, ученые, занимающиеся исследованиями и рабочие, занятые изготовлением товаров.
Иерархия будет состоять из базового типа: employee и трех производных классов: manager, scientist и laborer.

Слайд 40

#include
using namespace std;
const int len=80;
class employee
{ protected:
int nom;
char name[len];

#include using namespace std; const int len=80; class employee { protected: int
public:
void getdata()
{ cout<<"vvod N: "; cin>>nom;
cout<<"vvod FIO: “; cin>>name; }
void putdata()
{cout<<" N: " < } };

Слайд 41

class manager:public employee
{ private:
char title[len];
int kol;
public:
void getdata()
{

class manager:public employee { private: char title[len]; int kol; public: void getdata()
employee::getdata();
cout<<"vvod dolgnosty: "; cin>>title;
cout<<"vvod kolvo: "; cin>>kol;
}
void putdata()
{ employee::putdata();
cout<<"\n dolgnosty: "< cout<<"\n kol-vo prodag: " < } };

Слайд 42

class scientist:public employee
{ private:
int pubs;
public:
void getdata()
{ employee::getdata();

class scientist:public employee { private: int pubs; public: void getdata() { employee::getdata();
cout<<"vvod kolva pubs: "; cin>>pubs;
}
void putdata()
{ employee::putdata();
cout<<"\n publication: "< }
};
class laborer:public employee
{ };

Слайд 43

int main(int argc, char *argv[])
{ employee x; manager y;
scientist z; laborer

int main(int argc, char *argv[]) { employee x; manager y; scientist z;
w;
cout<<"vvod svedenij o 4 sotrudnikax:\n";
x.getdata();
y.getdata();
z.getdata();
w.getdata();
cout<<"vivod information about sotrudnikax:\n";
x.putdata();
y.putdata();
z.putdata();
w.putdata();
return 0;
}

Слайд 44

Производный класс может являться базовым для других производных классов.
Например:
class A
{ … };
class

Производный класс может являться базовым для других производных классов. Например: class A
B: public A
{ …};
class C:public B
{…};
Здесь класс B является производным класса А, а класс С производным класса B.

Слайд 45

Класс может являться производным как одного базового класса, так и нескольких базовых

Класс может являться производным как одного базового класса, так и нескольких базовых
классов (множественное наследование).
Например:
class A
{ … };
class B
{ …};
class C: public A, public B
{…};
Базовые классы перечисляются через запятую после знака :

Слайд 46

Работа с объектами чаще всего производится через указатели, например:
employee *р;
Указателю на базовый

Работа с объектами чаще всего производится через указатели, например: employee *р; Указателю
класс можно присвоить значение адреса объекта любого производного класса:
р = new laborer; или p=&y;
Где y описана, как: manager y;
Обращение к методу через указатель имеет вид:
p->getdata();
р->putdata();

Слайд 47

Виртуальные методы. Полиморфизм.
Полиморфизм — один из важнейших механизмов ООП. Полиморфизм реализуется с помощью

Виртуальные методы. Полиморфизм. Полиморфизм — один из важнейших механизмов ООП. Полиморфизм реализуется
наследования классов и виртуальных методов.
Полиморфизм состоит в том, что с помощью одного и того же обращения к методу выполняются различные действия в зависимости от типа, на который ссылается указатель в каждый момент времени.
Рассмотрим пример иерархии классов, где каждый класс имеет метод с одним именем.

Слайд 48

class Base
{
public:
void show()
{ cout<<“Родитель\n";
}
};
class derv1:public Base
{public:
void show()

class Base { public: void show() { cout } }; class derv1:public
{ cout<<"Сын первый\n";
}
};

Слайд 49

class derv2:public Base
{public:
void show()
{ cout<<"Сын второй\n";
}
};
int main(int argc, char

class derv2:public Base {public: void show() { cout } }; int main(int
*argv[])
{
derv1 s1; derv2 s2;
Base *ptr;
ptr=&s1;
ptr->show();
ptr=&s2;
ptr->show();

Слайд 50

Итак, классы derv1 и derv2 являются наследниками класса Base. В каждом из

Итак, классы derv1 и derv2 являются наследниками класса Base. В каждом из
трех классов имеется метод show(). В main() созданы объекты порожденных классов s1 и s2 и указатель на класс Base. Затем адрес объекта порожденного класса мы заносим в указатель базового класса: ptr=&s1;
Какая же функция будет выполняться в следующей строке:
ptr->show(); Base::show( ) или derv1::show( )?
В этом случае компилятор выбирает метод, удовлетворяющий типу указателя (Base::show())

Слайд 51

Этот процесс ,называется ранним связыванием.

Этот процесс ,называется ранним связыванием.

Слайд 52

В C++ реализован механизм позднего связывания, когда разрешение ссылок на метод происходит

В C++ реализован механизм позднего связывания, когда разрешение ссылок на метод происходит
на этапе выполнения программы в зависимости от конкретного типа объекта, вызвавшего метод. Этот механизм реализован с помощью виртуальных методов.
Для определения виртуального метода используется спецификатор virtual, например:
class base
{
public:
virtual void show()
{ cout<<"base\n";
}
};

Слайд 53

Этот процесс ,называется поздним связыванием.

Этот процесс ,называется поздним связыванием.

Слайд 54

Если в базовом классе метод определен как виртуальный, метод, определенный в производном

Если в базовом классе метод определен как виртуальный, метод, определенный в производном
классе с тем же именем и набором параметров, автоматически становится виртуальным, а с отличающимся набором параметров — обычным.
Для каждого класса (не объекта!), содержащего хотя бы один виртуальный метод,
компилятор создает таблицу виртуальных методов (vtbl), в которой для каждого виртуального метода записан его адрес в памяти.

Слайд 55

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

Рекомендуется делать виртуальными деструкторы для того, чтобы гарантировать правильное освобождение памяти из-под
динамического объекта, поскольку в этом случае в любой момент времени будет выбран деструктор, соответствующий фактическому типу объекта.
Деструктор передает операции delete размер объекта.

Слайд 56

Обзор стандартных библиотек С++
Развитие объектно - ориентированного программирования привело к созданию широкого

Обзор стандартных библиотек С++ Развитие объектно - ориентированного программирования привело к созданию
набора библиотек.
Библиотека STL/CLR представляет собой упакованную библиотеку стандартных шаблонов (STL), входящую в состав стандартной библиотеки C++.

Слайд 57

Библиотека содержит пять основных видов компонентов:
алгоритм (algorithm): определяет вычислительную процедуру.
контейнер (container):

Библиотека содержит пять основных видов компонентов: алгоритм (algorithm): определяет вычислительную процедуру. контейнер
управляет набором объектов в памяти.
итератор (iterator): обеспечивает для алгоритма средство доступа к содержимому контейнера.
функциональный объект (function object): инкапсулирует функцию в объекте для использования другими компонентами.
адаптер (adaptor): адаптирует компонент для обеспечения различного интерфейса.

Слайд 58

Алгоритмы реализуют большинство методов сортировки, поиска и т.п. ( )
Контейнеры – это

Алгоритмы реализуют большинство методов сортировки, поиска и т.п. ( ) Контейнеры –
объекты, содержащие другие однотипные объекты. В контейнерных классах реализованы такие типовые структуры, как стеки , списки , очереди и т.д.
Итераторы – это обобщение концепции указателей: они ссылаются на элементы контейнера .
Рассмотрим пример, реализующий работу стека с помощью стандартной библиотеки шаблонов.

Слайд 59

Рассмотрим основные методы класса stack:
push - метод для добавления элемента в стек.
pop

Рассмотрим основные методы класса stack: push - метод для добавления элемента в
– удаляет элемент из стека, но не возвращает удаленное значение.
top – возвращает значение с вершины стека.
empty – проверяет наличие элементов в стеке.

Слайд 60

#include
#include
#include
using namespace std;
int main(int argc, char *argv[])
{ stackx;
for(int i=1;

#include #include #include using namespace std; int main(int argc, char *argv[]) {
i<5; i++)
x.push(i); //записать в стек числа
while(!x.empty()) //если стек не пуст?
{cout<x.pop();} //удалить число из стека
return 0;
}

Слайд 61

Библиотека ATL расшифровывается как Active Template Library. Это библиотека классов и шаблонов,

Библиотека ATL расшифровывается как Active Template Library. Это библиотека классов и шаблонов,
предназначенная для разработки собственных компонетов. Одно из применений этой библиотеки - это создание собственных элементов ActiveX. Например, с помощью библиотеки ATL вы можете создать собственную особую кнопку (скажем, круглую) и затем использовать ее в программах.
Библиотека MFC (Microsoft Foundation Classes) предназначена в основном для создания приложений с пользовательским интерфейсом (окна, диалоги и т. п.).

Слайд 62

AfxMessageBox ( )

Библиотека MFC инкапсулирует многие функции API (Application Programming Interfase), с помощью

AfxMessageBox ( ) Библиотека MFC инкапсулирует многие функции API (Application Programming Interfase),
которых реализуются все необходимые системные действия, такие как выделение памяти, вывод на экран, создание окон и т.п. Библиотека MFC разрабатывалась для упрощения задач, стоящих перед программистом.
Кроме этого в языке С++ имеются библиотеки для параллельного программирования: Concurrency Runtime для С++ и OpenMP (Open Multi-Processing).

Слайд 63

Библиотека классов .NET Framework имеет следующие возможности:
библиотека базовых классов,такие как строки,

Библиотека классов .NET Framework имеет следующие возможности: библиотека базовых классов,такие как строки,
массивы и элементы форматирования;
передача данных по сети;
система безопасности;
удаленная обработка;
диагностика;
ввод/вывод;
базы данных;
язык ХМL;
Web-программирование;
пользовательский интерфейс ОС Windows.

Слайд 64

Если мы захотим создать Windows – приложение с помощью технологии .NET, то

Если мы захотим создать Windows – приложение с помощью технологии .NET, то
открыв Visual Studio, и выбрав Файл -> Создать -> Проект, выбираем пункт CLR, отмечаем Приложение Windows Forms и даем имя проекта: