Классы, структуры и пространства имен
C# является полноценным объектно-ориентированным языком. Это значит, что программу на C# можно представить в виде взаимосвязанных взаимодействующих между собой объектов.
Описанием объекта является класс , а объект представляет экземпляр этого класса. Можно еще провести следующую аналогию. У нас у всех есть некоторое представление о человеке, у которого есть имя, возраст, какие-то другие характеристики. То есть некоторый шаблон — этот шаблон можно назвать классом. Конкретное воплощение этого шаблона может отличаться, например, одни люди имеют одно имя, другие — другое имя. И реально существующий человек (фактически экземпляр данного класса) будет представлять объект этого класса.
В принципе ранее уже использовались классы. Например, тип string , который представляет строку, фактически является классом. Или, например, класс Console , у которого метод WriteLine() выводит на консоль некоторую информацию. Теперь же посмотрим, как мы можем определять свои собственные классы.
По сути класс представляет новый тип, который определяется пользователем. Класс определяется с помощью ключевого слова сlass :
class название_класса < // содержимое класса >
После слова class идет имя класса и далее в фигурных скобках идет собственно содержимое класса. Например, определим в файле Program.cs класс Person, который будет представлять человека:
class Person

Начиная с версии C# 12, если класс имеет пустое определение, то фигурные скобки после названия типа можно не использовать:
class Person;
Однако такой класс не особо показателен, поэтому добавим в него некоторую функциональность.
Поля и методы класса
Класс может хранить некоторые данные. Для хранения данных в классе применяются поля . По сути поля класса — это переменные, определенные на уровне класса.
Кроме того, класс может определять некоторое поведение или выполняемые действия. Для определения поведения в классе применяются методы.
Итак, добавим в класс Person поля и методы:
class Person < public string name = "Undefined"; // имя public int age; // возраст public void Print() < Console.WriteLine($"Имя: Возраст: "); > >
В данном случае в классе Person определено поле name , которое хранит имя, и поле age , которое хранит возраст человека. В отличие от переменных, определенных в методах, поля класса могут иметь модификаторы, которые указываются перед полем. Так, в данном случае, чтобы все поля были доступны вне класса Person поля определены с модификатором public .
При определении полей мы можем присвоить им некоторые значения, как в примере выше в случае переменной name . Если поля класса не инициализированы, то они получают значения по умолчанию. Для переменных числовых типов это число 0.
Также в классе Person определен метод Print() . Методы класса имеют доступ к его поля, и в данном случае обращаемся к полям класса name и age для вывода их значения на консоль. И чтобы этот метод был виден вне класса, он также определен с модификатором public .
Создание объекта класса
После определения класса мы можем создавать его объекты. Для создания объекта применяются конструкторы . По сути конструкторы представляют специальные методы, которые называются так же как и класс, и которые вызываются при создании нового объекта класса и выполняют инициализацию объекта. Общий синтаксис вызова конструктора:
new конструктор_класса(параметры_конструктора);
Сначала идет оператор new , который выделяет память для объекта, а после него идет вызов конструктора .
Конструктор по умолчанию
Если в классе не определено ни одного конструктора (как в случае с нашим классом Person), то для этого класса автоматически создается пустой конструктор по умолчанию, который не принимает никаких параметров.
Теперь создадим объект класса Person:
Person tom = new Person(); // создание объекта класса Person // определение класса Person class Person < public string name = "Undefined"; public int age; public void Print() < Console.WriteLine($"Имя: Возраст: "); > >

Для создания объекта Person используется выражение new Person() . В итоге после выполнения данного выражения в памяти будет выделен участок, где будут храниться все данные объекта Person. А переменная tom получит ссылку на созданный объект, и через эту переменную мы можем использовать данный объект и обращаться к его функциональности.
Обращение к функциональности класса
Для обращения к функциональности класса — полям, методам (а также другим элементам класса) применяется точечная нотация точки — после объекта класса ставится точка, а затем элемент класса:
объект.поле_класса объект.метод_класса(параметры_метода)
Например, обратимся к полям и методам объекта Person:
Person tom = new Person(); // создание объекта класса Person // Получаем значение полей в переменные string personName = tom.name; int personAge = tom.age; Console.WriteLine($"Имя: Возраст "); // Имя: Undefined Возраст: 0 // устанавливаем новые значения полей tom.name = "Tom"; tom.age = 37; // обращаемся к методу Print tom.Print(); // Имя: Tom Возраст: 37 class Person < public string name = "Undefined"; public int age; public void Print() < Console.WriteLine($"Имя: Возраст: "); > >
Консольный вывод данной программы:
Имя: Undefined Возраст: 0 Имя: Tom Возраст: 37
Добавление класса
Обычно классы помещаются в отдельные файлы. Нередко для одного класса предназначен один файл. Если мы работаем над проектом вне среды Visual Studio, используя .NET CLI, то нам достаточно добавить новый файл класса в папку проекта. Например, добавим новый файл, который назовем Person.cs и в котором определим следующий код:
class Person < public string name = "Undefined"; public void Print() < Console.WriteLine($"Person "); > >
Здесь определен класс Person с одним полем name и методом Print.
В файле Program.cs , который представляет основной файл программы используем класс Person:
Person tom = new Person(); tom.name = "Tom"; tom.Print(); // Person Tom

Visual Studio предоставляет по умолчанию встроенные шаблоны для добвления класса. Для добавления класса нажмем в Visual Studio правой кнопкой мыши на название проекта:

В появившемся контекстном меню выберем пункт Add -> New Item. (или Add -> Class. )
В открывшемся окне добавления нового элемента убедимся, что в центральной части с шаблонами элементов у нас выбран пункт Class . А внизу окна в поле Name введем название добавляемого класса — пусть он будет назваться Person :

В качестве названия класса можно вводить как Person, так и Person.cs. И после нажатия на кнопку добавления в проект будет добавлен новый класс, в котором можно определить тот же код и также использовать в файле Program.cs.
Таким образом, мы можем определять классы в отдельных файлах и использовать их в программе.
Как подключить класс c
Для выполнения различных математических операций в библиотеке классов .NET предназначен класс Math . Он является статическим, поэтому все его методы также являются статическими.
Рассмотрим основные методы класса Math:
-
Abs(double value) : возвращает абсолютное значение для аргумента value
double result = Math.Abs(-12.4); // 12.4
double result = Math.Acos(1); // 0
double result = Math.BigMul(100, 9340); // 934000
double result = Math.Ceiling(2.34); // 3
int result; int div = Math.DivRem(14, 5, out result); //result = 4 // div = 2
double result = Math.Floor(2.56); // 2
double result = Math.IEEERemainder(26, 4); // 2 = 26-24
double result1 = Math.Round(20.56); // 21 double result2 = Math.Round(20.46); //20
double result1 = Math.Round(20.567, 2); // 20,57 double result2 = Math.Round(20.463, 1); //20,5
int result1 = Math.Sign(15); // 1 int result2 = Math.Sign(-5); //-1
double result1 = Math.Sqrt(16); // 4
double result = Math.Truncate(16.89); // 16
Также класс Math определяет две константы: Math.E и Math.PI . Например, вычислим площадь круга:
double radius = 50; double area = Math.PI * Math.Pow(radius, 2); Console.WriteLine($"Площадь круга с радиусом равна "); Площадь круга с радиусом 50 равна 7853,98
- Глава 1. Введение в C#
- Язык C# и платформа .NET
- Первая программа на C# с .NET CLI
- Начало работы с Visual Studio. Первая программа
- Первое приложение в WSL
- Структура программы
- Переменные и константы
- Литералы
- Типы данных
- Консольный ввод-вывод
- Арифметические операции
- Поразрядные операции
- Операции присваивания
- Преобразования базовых типов данных
- Условные выражения
- Конструкция if..else и тернарная операция
- Циклы
- Массивы
- Задачи с массивами
- Методы
- Параметры методов
- Возвращение значения и оператор return
- Передача параметров по ссылке и значению. Выходные параметры
- Массив параметров и ключевое слово params
- Рекурсивные функции
- Локальные функции
- Конструкция switch
- Перечисления enum
- Классы и объекты
- Конструкторы, инициализаторы и деконструкторы
- Класс Program и метод Main. Программы верхнего уровня
- Структуры
- Типы значений и ссылочные типы
- Область видимости (контекст) переменных
- Пространства имен
- Глобальные пространства имен
- Подключение пространств имен по умолчанию
- Создание библиотеки классов в Visual Studio
- Создание библиотеки классов с помощью .NET CLI
- Модификаторы доступа
- Свойства
- Перегрузка методов
- Статические члены и модификатор static
- Установка пакетов Nuget
- Константы, поля и структуры для чтения
- Null и ссылочные типы
- Null и значимые типы
- Проверка на null, операторы ?. и ??
- Псевдонимы типов и статический импорт
- Наследование
- Преобразование типов
- Виртуальные методы и свойства
- Скрытие методов и свойств
- Различие переопределения и скрытия методов
- Абстрактные классы
- Класс System.Object и его методы
- Обобщенные типы
- Ограничения обобщений
- Наследование обобщенных типов
- Конструкция try..catch..finally
- Блок catch и фильтры исключений
- Типы исключений. Класс Exception
- Генерация исключения и оператор throw
- Создание классов исключений
- Поиск блока catch при обработке исключений
- Делегаты
- Применение делегатов
- Анонимные методы
- Лямбды
- События
- Ковариантность и контравариантность делегатов
- Делегаты Action, Predicate и Func
- Замыкания
- Определение интерфейсов
- Применение интерфейсов
- Явная реализация интерфейсов
- Реализация интерфейсов в базовых и производных классах
- Наследование интерфейсов
- Интерфейсы в обобщениях
- Копирование объектов. Интерфейс ICloneable
- Сортировка объектов. Интерфейс IComparable
- Ковариантность и контравариантность обобщенных интерфейсов
- Определение операторов
- Перегрузка операций преобразования типов
- Индексаторы
- Переменные-ссылки и возвращение ссылки
- Методы расширения
- Частичные классы и методы
- Анонимные типы
- Кортежи
- Records
- Паттерн типов
- Паттерн свойств
- Паттерны кортежей
- Позиционный паттерн
- Реляционный и логический паттерны
- Паттерны списков
- Список List
- Двухсвязный список LinkedList
- Очередь Queue
- Стек Stack
- Словарь Dictionary
- Класс ObservableCollection
- Интерфейсы IEnumerable и IEnumerator
- Итераторы и оператор yield
- Класс Array и массивы
- Span
- Индексы и диапазоны
- Строки и класс System.String
- Операции со строками
- Форматирование и интерполяция строк
- Класс StringBuilder
- Регулярные выражения
- Структура DateTime
- Форматирование дат и времени
- DateOnly и TimeOnly
- Отложенная инициализация и тип Lazy
- Математические вычисления и класс Math
- Преобразование типов и класс Convert
- Введение в многопоточность. Класс Thread
- Создание потоков. Делегат ThreadStart
- Потоки с параметрами и ParameterizedThreadStart
- Синхронизация потоков
- Мониторы
- Класс AutoResetEvent
- Мьютексы
- Семафоры
- Задачи и класс Task
- Работа с классом Task
- Задачи продолжения
- Класс Parallel
- Отмена задач и параллельных операций. CancellationToken
- Асинхронные методы, async и await
- Возвращение результата из асинхронного метода
- Последовательное и параллельное выполнение. Task.WhenAll и Task.WhenAny
- Обработка ошибок в асинхронных методах
- Асинхронные стримы
- Основы LINQ
- Проекция данных
- Фильтрация коллекции
- Сортировка
- Объединение, пересечение и разность коллекций
- Агрегатные операции
- Получение части коллекции
- Группировка
- Соединение коллекций
- Проверка наличия и получение элементов
- Отложенное и немедленное выполнение LINQ
- Делегаты в запросах LINQ
- Введение в Parallel LINQ. Метод AsParallel
- Метод AsOrdered
- Обработка ошибок и отмена параллельных операции
- Введение в рефлексию. Класс System.Type
- Применение рефлексии и исследование типов
- Исследование методов и конструкторов с помощью рефлексии
- Исследование полей и свойств с помощью рефлексии
- Динамическая загрузка сборок и позднее связывание
- Атрибуты в .NET
- DLR в C#. Ключевое слово dynamic
- DynamicObject и ExpandoObject
- Использование IronPython в .NET
- Сборщик мусора в C#
- Финализируемые объекты. Метод Dispose
- Конструкция using
- Указатели
- Указатели на структуры, члены классов и массивы
- Работа с дисками
- Работа с каталогами
- Работа с файлами. Классы File и FileInfo
- FileStream. Чтение и запись файла
- Чтение и запись текстовых файлов. StreamReader и StreamWriter
- Бинарные файлы. BinaryWriter и BinaryReader
- Архивация и сжатие файлов
- Сериализация в JSON. JsonSerializer
- XML-Документы
- Работа с XML с помощью System.Xml
- Изменение XML-документа
- XPath
- Linq to Xml. Создание Xml-документа
- Выборка элементов в LINQ to XML
- Изменение документа в LINQ to XML
- Сериализация в XML. XmlSerializer
- Процессы
- Домены приложений
- AssemblyLoadContext и динамическая загрузка и выгрузка сборок
- Native AOT
- Нововведения в C# 11
- Нововведения в C# 12
Помощь сайту
410011174743222
Перевод на карту
Номер карты:
4048415020898850Контакты для связи: metanit22@mail.ru
Copyright © metanit.com, 2024. Все права защищены.
Подключение классов
C++, Visual Studio 2013
Как правильно подключать классы, если имеется следующая структура: Файл Base.h:class base<>;Файл Child1.h:
#include "base.h" class Child : public base
Файл Child2.h:
#include "base.h" class Child2 : public baseФайл Main.h:
#include "Child.h" #include "Child2.h"При таком включении получаю ошибку линковки: переопределение класса base
Отслеживать
29k 14 14 золотых знаков 61 61 серебряный знак 119 119 бронзовых знаков
задан 13 апр 2016 в 10:44
73 1 1 серебряный знак 6 6 бронзовых знаков2 ответа 2
Сортировка: Сброс на вариант по умолчанию
Скорее всего, у вас в h файлах отсутствует защита от двойного включения. Самый простой способ — добавить #pragma once в самый верх каждого .h файла или сделать по старинке — завернуть в охранный «гуард»
#ifndef _FILENAME_H_ #define _FILENAME_H_ // тут код #endif_FILENAME_H_ — должно быть уникально для каждого файла, поэтому, обычно оно совпадает с именем файла. Этот способ работает на практически всех доступных компиляторах с/с++. pragma once может не работать на старых компиляторах.
Отслеживать
ответ дан 13 апр 2016 в 10:49
112k 6 6 золотых знаков 94 94 серебряных знака 161 161 бронзовый знак
на практически всех . встречали случаи, где не работало?
13 апр 2016 в 11:13да, я пользовался c комилятором, в котором не было define. Просто не было. Компилятор был по хитрые контроллеры, сейчас даже не вспомню. Автор вопроса вряд ли столкнется с подобным, но мало чего .
13 апр 2016 в 12:00
В таком случае это не может называться c компилятором в полной мере. Это просто какая-то поделка. И кстати, вопрос ТС по c++ .
13 апр 2016 в 12:07
я вкурсе, что вопрос по с++. А подделкой приходилось пользоваться, так как другого не было. А писать код прям в кодах мне не хотелось. Правда потом был прикручен препроцессор и все работало так как хотелось (да, если сильно быть педантом, обработка #ifdef — это работа препроцессора, а не компилятора. И как следствие ниодин правильный компилятор не поддерживает. Но современные компиляторы это скрывают и делают препроцессирование самостоятельно).
13 апр 2016 в 12:12
Понятно, что это работа препроцессора, но препроцессорные директивы тем не менее описаны в Стандарте по языку. И я бы отнес это к базовой части того, что реализация должна уметь. Иначе можно придумать и компиляторы, которые, скажем, не имеют оператора if . Но назвать такое компилятором си, язык не поворачивается.
Как подключить класс c
Нередко различные классы и структуры оформляются в виде отдельных библиотек, которые компилируются в файлы dll и затем могут подключаться в другие проекты. Благодаря этому мы можем определить один и тот же функционал в виде библиотеки классов и подключать в различные проекты или передавать на использование другим разработчикам.
Создадим и подключим библиотеку классов.
Возьмем имеющийся проект консольного приложения C#, например, созданный в прошлых темах. В структуре проекта нажмем правой кнопкой на название решения и далее в появившемся контекстном меню выберем Add -> New Project. (Добавить новый проект):

Далее в списке шаблонов проекта найдем пункт Class Library :

Затем дадим новому проекту какое-нибудь название, например, MyLib:

После создания этого проекта в решение будет добавлен новый проект, в моем случае с названием MyLib:

По умолчанию новый проект имеет один пустой класс Class1 в файле Class1.cs. Мы можем этот файл удалить или переименовать, как нам больше нравится.
Например, переименуем файл Class1.cs в Person.cs, а класс Class1 в Person. Определим в классе Person простейший код:
namespace MyLib < public class Person < string name; public Person(string name) < this.name = name; >public void Print() => Console.WriteLine($"Name: "); > >

Теперь скомпилируем библиотеку классов. Для этого нажмем правой кнопкой на проект библиотеки классов и в контекстном меню выберем пункт Rebuild :

После компиляции библиотеки классов в папке проекта в каталоге bin/Debug/net6.0 мы сможем найти скомпилированный файл dll (MyLib.dll). Подключим его в основной проект. Для этого в основном проекте нажмем правой кнопкой на узел Dependencies и в контекстном меню выберем пункт Add Project Reference. :

Далее нам откроется окно для добавления библиотек. В этом окне выберем пункт Solution,который позволяет увидеть все библиотеки классов из проектов текущего решения, поставим отметку рядом с нашей библиотекой и нажмем на кнопку OK:

Если наша библиотека вдруг представляет файл dll, который не связан ни с каким проектом в нашем решении, то с помощью кнопки Browse мы можем найти местоположение файла dll и также его подключить.
После успешного подключения библиотеки в главном проекте изменим файл Program.cs , чтобы он использовал класс Person из библиотеки классов:
using MyLib; // подключение пространства имен из библиотеки классов Person tom = new("Tom"); tom.Print(); // Name: Tom