Как разбить программу на файлы c

Обновлено: 06.07.2024

Пример разработки программы, которая размещается в разных файлах. Реализация наследования в классах. Средства MS Visual Studio 2019 разбивки программы на части

При создании иерархий классов, содержащих большие объемы программного кода, целесообразно реализовывать каждый класс в отдельном файле (модуле). Разбивка объемных программ на отдельные части (файлы) имеет следующие преимущества:

  • облегчает восприятие общей структуры программы;
  • ускоряет поиск нужных фрагментов кода;
  • уменьшает количество трудноуловимых ошибок, связанных с разнообразием кодов сконцентрированных в одном файле.

В данном примере с помощью средств Microsoft Visual Studio 19 разработана программа, код которой разбит на части. Каждая часть программы реализована в отдельном файле. С целью удобства использования, в каждом файле объявляется отдельный класс. Имя каждого файла совпадает с именем класса, который в нем реализован.
Пример демонстрирует реализацию 3 классов, взаимодействующих между собой с помощью отношения наследования (отношение is-a).

Содержание

  • Условие задачи
  • Выполнение
    • 1. Создание проекта по шаблону Console Application
    • 2. Начальная конфигурация программы
    • 3. Добавление класса Human и файла Human.cs
    • 4. Добавление класса Citizen и файла Citizen.cs
    • 5. Добавление класса ForeignCitizen и файла ForeignCitizen.cs
    • 6. Структура программы
    • 7. Программный код класса Human
    • 8. Программный код класса Citizen
    • 9. Программный код класса ForeignCitizen
    • 10. Текст функции Main() . Тестирование работы программы
    • 11. Результат работы программы

    Поиск на других ресурсах:

    Условие задачи

    Реализовать иерархию классов. Базовый класс Human содержит информацию:

    От класса Human нужно унаследовать производный класс Citizen , который содержит следующую информацию:

    От класса Citizen нужно унаследовать производный класс ForeignCitizen , который содержит дополнительную информацию:

    • номер загранпаспорта;
    • дата открытия визы;
    • дата окончания визы.

    Во всех классах должны быть следующие элементы:

    • конструктор с параметрами, инициализирующий поля конкретного класса;
    • свойства get / set для доступа к полям классов;
    • метод Print() , который выводит информацию о полях класса на экран.

    Выполнение

    1. Создание проекта по шаблону Console Application

    После запуска MS Visual Studio 2019 нужно создать новый проект. Это осуществляется стандартным способом с помощью последовательности команд

    Если Visual Studio 2019 только что запустился на выполнение, то система автоматически откроет соответствующее окно, в котором можно создать новый проект или выбрать уже существующие проекты.

    С помощью оконного интерфейса нужно выполнить следующие действия (рисунок 1):

    MS Visual Studio 2019. Окно "Create a New Project". Создание нового проекта

    2. Начальная конфигурация программы

    На данный момент программа состоит из одного файла Program.cs . В этом файле объявляется класс Program , который содержит точку входа в программу – статическую функцию Main() .

    На данный момент текст модуля Program.cs следующий

    3. Добавление класса Human и файла Human.cs

    В этом пункте подробно описывается добавление нового файла к проекту. В соответствии с условием задачи, класс Human должен быть реализован в файле (модуле) human.cs .

    Система Visual Studio 2019 (да и другие версии) построена таким образом, что при добавлении нового класса с помощью интерфейса Visual Studio, этот класс автоматически будет размещаться в новом файле. Нужно только указать имя этого файла.

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

    как показано на рисунке 3.

    В результате выполненных действий будет создан класс Human , который размещается в файле Human.cs (рисунок 5).

    Рисунок 5. Окно программы с активным файлом Human.cs

    Как видно из рисунка 5, на данный момент программа состоит из двух файлов:

    • Human.cs – файл, в котором размещается класс Human ;
    • Program.cs – файл, в котором размещается класс Program .

    Оба класса размещаются в одном пространстве имен DemoSplitFiles .

    Текст класса Human пока что следующий

    4. Добавление класса Citizen и файла Citizen.cs

    На этом этапе нужно добавить класс Citizen и файл Citizen.cs . Добавление класса Citizen осуществляется по образцу добавления класса Human (смотрите предыдущий пункт 2.3).

    После того, как класс Citizen будет добавлен, текст файла Citizen.cs будет следующим

    Класс Citizen размещается в пространстве имен DemoSplitFiles как и предыдущие классы Program и Human .

    5. Добавление класса ForeignCitizen и файла ForeignCitizen.cs

    По образцу предыдущих классов Human , Citizen добавляется класс ForeignCitizen . После добавления, класс размещается в отдельном файле ForeignCitizen.cs и содержит следующий код

    6. Структура программы

    На данный момент программа состоит из 4 файлов:

    • Program.cs – содержит текст класса Program , в котором описывается статическая функция Main() . Эта функция есть точкой входа в программу, она выполняется первой при запуске приложения;
    • Human.cs – содержит текст класса Human , который есть базовым для классов Citizen и ForeignCitizen ;
    • Citizen.cs – содержит текст класса Citizen , который унаследован от класса Human и есть базовым для класса ForeignCitizen ;
    • ForeignCitizen.cs – содержит текст класса ForeignCitizen , который унаследован от класса Citizen .
    7. Программный код класса Human

    В соответствии с условием задачи класс Human есть базовым в иерархии классов. Текст класса Human следующий:

    Доброго времени суток.
    Подскажите пожалуйста, как правильно выносить код в разные файлы в c++?
    Пишу программу, она уже разрослась на 3000+ строк кода и всё это в одной cpp файле!
    Как мне правильно разделить код в разные файлы?

    Попутный вопрос: было бы здорово вынести код в отдельные dll, но насколько это сложно и где это почитать?

    • Вопрос задан более трёх лет назад
    • 12004 просмотра

    Сложность этого действия зависит от двух факторов:
    - от качества кода на данный момент
    - от качества того, что хотите получить на выход

    По первому пункту, если у вас код грамотно разбит на классы и/или функции, то проблемы быть не должно. Как уже писали, просто вынесите все определения в хедеры, все остальное оставьте в .cpp . С другой стороны, я себе слабо представляю как написать грамотный код в одном файле.
    Это приводит нас ко второму пункту. Для того, чтобы в итоге получился качественный продукт, необходимо логическое разделение на подзадачи. Если это выполнить грамотно это приведет к небольшим функциям, которые всегда делают что-то одно и/или к небольшим классам, которые отвечают за одну сущность. Такую структуру легко вынести в разные файлы.
    Если же у вас много глобальных переменных и тп, то код тоже можно легко разнести в разные файлы, но с группировкой по файлам будет сложно, да и смысла в этом много не будет.

    ПС. Не уверен, знаете ли вы, но не забывайте в каждом .h файле:

    это убережет вас от последущих повторных включений этого файла.

    Несложно.
    Определитесь сначала с модулями и интерфейсами.
    В .h файлы выносите сигнатуры и типы, реализация - в cpp файлах, в которые приинклюжен нужный h файл.

    с дллками легко - нужнен только префикс declspec(dllexport) для экспортируемых и declspec(dllimport) для импортируемых, но есть макрос, заменяющийся на это автоматом

    Это действует, если человек без шаблонов пишет. С шаблонами и разделением на .h и .cpp сложнее. Выносить код в отдельную dll имеет смысл только если нужно запускать несколько экземпляров вашей программы, либо в dll можно вынести какой-то специфичный код, который зависит от типа Операционной системы или других факторов (нп. создание тестовой библиотеки и полноценной)
    Про разбиение одного файла на несколько - тут @KOLANICH верно описал. Добавлю, что в заголовочные файлы (.h) желательно не размещать ничего, кроме определения типов и классов, а также описания сигнатур функций: т.е. ни глобальных переменных, ни тел реализаций функций тут быть не должно, в общем - ни какой логики.
    А также стараться поменьше включать заголовочные файлы друг в друга - потом на грабли с очерёдностью компиляции наткнётесь.

    Kerman

    Вам нужен рефакторинг. То, что Вы описали, говорит о том, что Ваш код далёк от совершенства.
    Вам нужно для начала применить extract method, затем exctract class или подобные методы. После чего можно будет спокойно классы разнести по отдельным файлам.

    А для чего нужно разбивать на несколько DLL ? Может просто переоформить код,т.е провести рефакторинг и оставить все как есть в рамках одной DLL?

    Я бы Вам посоветовал Пока "жить" в рамках одной DLL и провести рефакторинг, тогда внешняя программа что использует вашу DLL послужит хорошим тестовым стендом и провести проверочное тестирование после рефакторинга будет значительно проще! Вторым этапом, если Вы все же решите разбить на несколько DLL Вам будет значительно проще,т.к. понятный код и он протестирован!

    Разбивается путем мышления и задавание себе вопросов.
    Каждый модуль обязан отвечать утвердительно на вопрос "Он действительно решает только одну задачу?". При этом надо понимать не примитивные задачи "чтение из файла" или "подсчитать энтропию", под "одной задачей" понимает один пункт взятый с уровня абстракции.

    Пример:
    Уровень 1: Чтение настроек
    Под-уровень 1: Формирование имени файла с настройками
    Под-уровень 2: Открытие и чтение из файла с настойками
    Под-уровень 3: Задание глобального объекта конфигуратор соглассно прочитанным настройками
    и т.д. и т.п.

    В любом случае идеальных методик по разбиению нет! Вас никто не научит программировать, это процесс итеративный, сегодня лучше чем вчера, а завтра будет еще лучше чем сегодня ;)

    Как только программы становятся больше, их следует разбивать на несколько файлов (в целях удобства и улучшения функциональности). Одним из преимуществ использования IDE является легкость в работе с n-ным количеством файлов. Мы уже знаем, как создавать и компилировать однофайловые проекты, добавление новых файлов не составит труда.

    Многофайловые проекты в Visual Studio

    В Visual Studio щелкните правой кнопкой мыши по имени вашего проекта в "Обозревателе решений" , затем "Добавить" > "Создать элемент. " :


    Во всплывающем диалоговом окне выберите тип файла, укажите его имя, расположение, а затем нажмите "Добавить" :


    Также вы можете добавлять файлы к вашему проекту через "Проект" > "Добавить новый элемент. " :



    Многофайловые проекты в Code::Blocks

    В Code::Blocks перейдите в "File" > "New" > "File. " :


    Затем выберите "C/C++ source" и нажмите "Go" :


    Затем "Next" (этого окна может и не быть):


    Затем "C++" и опять "Next" :


    Затем укажите имя нового файла (не забудьте расширение .cpp) и его расположение (нажмите на троеточие и выберите путь). Убедитесь, что поставлены все три галочки (они отвечают за конфигурации сборки). Затем нажмите "Finish" :


    Готово! Файл добавлен.

    Многофайловые проекты в GCC/G++

    В командной строке вам нужно будет создать файл, указать его имя и подключить к компиляции, например:

    g++ main.cpp add.cpp -o main

    Пример многофайловой программы

    Рассмотрим следующую программу, которая состоит из двух файлов.

    std :: cout << "The sum of 3 and 4 is: " << add ( 3 , 4 ) << std :: endl ;

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

    add: идентификатор не найден

    При компиляции кода, компилятор не знает о существовании функций, которые находятся в других файлах. Это сделано специально, чтобы функции и переменные с одинаковыми именами, но в разных файлах, не вызывали конфликт имен.

    Тем не менее, в данном случае, мы хотим, чтобы main.cpp знал (и использовал) функцию аdd(), которая находится в add.cpp. Для предоставления доступа main.cpp к функциям add.cpp, нам нужно использовать предварительное объявление:

    int add ( int x , int y ) ; // это нужно для того, чтобы main.cpp знал, что функция add() определена в другом месте std :: cout << "The sum of 3 and 4 is: " << add ( 3 , 4 ) << std :: endl ;

    Теперь, когда компилятор будет компилировать main.cpp, он будет знать, что такое add(). Попробуйте запустить эту программу еще раз.

    Что-то пошло не так!

    Пункт №1: Если вы получили ошибку от компилятора, что функция add() не определена в main(), то, скорее всего, вы забыли записать предварительное объявление функции add() в main.cpp.

    Пункт №2: Если вы получили следующую ошибку от линкера:

    unresolved external symbol "int __cdecl add(int,int)" (?add@@YAHHH@Z) referenced in function _main

    то возможных решений есть несколько:

    a) Cкорее всего, add.cpp некорректно добавлен в ваш проект. Если вы используете Visual Studio или Code::Blocks, то вы должны увидеть add.cpp в "Обозревателе решений" в списке файлов вашего проекта или в панели проекта IDE. Если добавленного файла нет, то щелкните правой кнопкой мыши по вашему проекту и добавьте файл, как это показано выше, а затем повторите попытку компиляции вашего проекта.

    б) Вполне возможно, что вы добавили add.cpp к другому проекту.

    в) Вполне возможно, что добавленный файл не подключен к компиляции/линкингу. Щелкните правой кнопкой мыши по имени вашего добавленного файла и выберите "Свойства" :


    Убедитесь, что пункт "Исключен из сборки" оставлен пустым или выбрано значение "Нет" :


    Пункт №3: Не следует писать следующую строку в main.cpp:

    Наличие этой строки приведет к тому, что компилятор вставит всё содержимое add.cpp непосредственно в main.cpp вместо того, чтобы рассматривать эти файлы как отдельные.

    Разделите следующую программу на два файла (main.cpp и input.cpp): main.cpp должен содержать функцию main(), а input.cpp — функцию getInteger().

    Помните, что для функции getInteger() вам понадобится предварительное объявление в main.cpp.

    Ответ

    int getInteger ( ) ; // предварительное объявление функции getInteger() (901 оценок, среднее: 4,88 из 5)

    Урок №19. Прототип функции и Предварительное объявление

    Комментариев: 50

    Я так понимаю, что при включении в главный файл заголовочный файл библиотеки, которые были в заголовочном файле копируются, что только прибавляет веса главному файлу или все же копирует лишь функции?

    Здравствуйте. А если у меня функция getInteger() будет определена в 2 и более файлах, то как файл с функцией main() поймет какой именно getInteger() мне требуется?

    Я методом тыка уже определил что будет ошибка )

    Юрий :

    Если вы подключите больше одного файла с определением одной и той же функции в проект, то получите ошибку компиляции. Функция определяется 1 раз в 1 файле.

    Юрий :

    Смотрите решение в уроке №7.

    Спасибо, Юрий! Замечательные уроки! Получаю удовольствие.. Возникают вопросы.. ищу на сайтах.. нахожу.. Будут посерьёзнее, намерен обращаться, если позволите!

    Юрий :

    Начал изучать С++ для создания игр на Unreal, но там все как то сложно.
    Случайно наткнулся на ваши уроки, это же просто чудо какое то)
    Спасибо за ваш труд.
    Пожалуй накидаю плюсиков в карму автору)

    Мне кажется стоило также указать что хорошим тоном является написать функцию в <name>.cpp, сделать её объявление в <name>.h, после чего подключить <name.h> в основном файле.

    Вместо того чтобы писать объявления функций напрямую.

    Первый файл с функцией int getInteger():

    Может кто-нибудь знает как это все осуществить при помощи Xcode, или статью какую-нибудь по обучению использования этой среды.

    А что сложного в Xcode? Всё по аналогии с VS, но со своими особенностями (если уж на то пошло). Можно нагуглить на крайний случай.

    Юрий :

    Здравствуйте я пишу в андроид с помощью Dcoder и хотел пройти тест в конце этого урока но у меня выдаёт ошибку.

    Спасибо за уроки, хороший язык оказывается.

    Срочно нужна помощь.
    Начал программировать на андроид с приложения Dcoder(c++: GCC compiler 6.3 (знаю, что это неудобно и т. д., но лучше так, чем никак).
    С этим уроком получилась зиминка из-за моего не состояния найти способ, как связать несколько файлов именно в этом приложении. Если кто-то что с этим делать, тогда пишите (буду очень благодарен). Автору спасибо за уроки. Всё очень доходчиво написано.

    Это символ переноса строки, такая управляющая последовательность(и гуглите 🙂 )

    Какая же чудесная находка для меня эти уроки) Автору огромное спасибо за проделанную работу за перевод и адаптацию

    Юрий : Юрий :

    Здравствуйте. Как добавлять файлы в Visual Studio 2017 если он на русском. Просто не очень понятно, переводчик не помогает.

    Юрий :

    Тогда я ошибся, и это чудесно =) Прошу прощения. Я не заметил ссылки, привык их искать где-то в аннотации.

    Юрий :

    Ничего, без проблем 🙂

    Добрый день! При попытке добавить в функцию, которая находится в отдельном файле, "stdafx.h" компилятор выдаёт ошибку: не удаётся открыть файл включения stdafx.h: No such file or directory. Без stdafx.h всё нормально работает. Visual Studio 2015.

    Юрий :

    Сегодня читала статью с телефона. Очень удобный сайт)

    Юрий :

    Когда пишу файл add.cpp постоянно не идёт,это ж линкер мешает по моему. И что ему не так,когда твою программу скопировал,также всё:

    Ошибка LNK2019 ссылка на неразрешенный внешний символ _main в функции "int __cdecl invoke_main(void)" (?invoke_main@@YAHXZ) add.cpp 1

    Юрий :

    Вы сделали всё как в уроке? Правильно добавили файл? К тому проекту, что нужно?

    Почему в VS нужно обязательно подключать библиотеку stdafx.h? Раньше, когда я учился по видеоурокам, я писал программы и без ее подключения. Но конечно есть одно но, я тогда немного изменил параметры создания проекта: поставил галочку на "Empty project" и удалил галочку на "Security Development Lifecycle (SDL) checks ". Может быть это как-то повлияло?

    Юрий :

    Зачем писать названия в VS (например Source Files) на английском, если в VS есть русский язык?

    Я организовал свою программу, разбив каждую сущность на отдельные файлы. Что - то вроде этого.

    Моя проблема в том, что внутри класса мне нужен ученик и предмет . Как я должен включить это? должен ли я включить это в classroom.h или classroom.c ?

    Во-вторых, у меня есть вещи на main.c , которые используются всеми тогда, как sum() и PI

    Как правильно включать реализацию в заголовок или включать заголовок в файл реализации? и должен ли я включать файлы заголовка или реализации?

    Если я бросаю все в один файл, он компилируется просто отлично, но я не делаю это правильно, он не компилируется.

    4 ответа

    Мне нужен совет, как сделать программу perl, которая сможет разбить файл на более мелкие файлы с помощью числовой строки. например: perl split.pl --file=data.txt --numberLine=2 вход data.txt: line1 line2 line3 line4 выход data1.txt line1 line2 data2.txt line3 line4 или perl split.pl.

    Первый. Одна вещь, которую важно знать о файлах .h (заголовочных). У них должно быть следующее.

    Зачем ставить это? Если бы вы включили свой заголовочный файл, скажем header.h , в несколько других файлов, file1.c , file2.c , вы бы в основном повторяли код, то есть код в header.h будет помещен в оба файла во время процесса компиляции.

    Наличие этих инструкций предварительного процессора гарантирует, что код в header.h будет существовать в программе только один раз.

    Если только classroom.c также использует вещи, объявленные в заголовках, поместите includes только здесь, но не в classroom.h .

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

    О sum() и PI . То же самое. Сделайте заголовок с приведенным выше кодом и включите его там, где это необходимо.

    Таким образом, организация "x.h" и "x.c" (или "x.cpp") - это довольно стандартный способ делать вещи. Но некоторые вещи там не вписываются, и иногда вам нужно "constants.h" или какое-то другое имя для таких вещей, как PI и SpeedOfLight .

    Что - то вроде sum хорошо вписалось бы в "utils.h" - достаточно ли у вас денег, чтобы иметь "utils.c"

    Ваш файл .c должен содержать все необходимые заголовочные файлы (но не более).

    Если я включу "x.h", я должен поставить перед ним "a.h" и "b.h".

    В то же время не добавляйте больше включений, чем вам действительно нужно.

    Ссылается CUDA Center Of Excellence, IIT Bombay Я работаю над распараллеливанием сетевого инструмента, но я не могу включить стандартные файлы c, такие как socket.h в kernel, потому что Kernel не поддерживает стандартные заголовочные файлы C, он понимает только некоторые предопределенные типы.

    Мне удалось написать программу C, которая копирует файлы из одного каталога в другой, и я пытаюсь написать программу, которая копирует каталоги и подкаталоги в другой каталог. Я также смог написать сценарий shell, который копирует каталоги и подкаталоги из одного места в другое. Итак, я хочу.

    Ваш вопрос в основном касается стиля.
    В лучшем случае люди могут дать вам общее мнение.

    Я думаю, что каждый файл должен выполнять конкретную работу или хорошо определять конкретный объект и связанные с ним операции.
    "job" должен быть описан простым способом:

    • Файл для общих (простых) процедур и/или macros и/или констант.
    • Файл для дескриптора строки.
    • Файл для целочисленной арифметики.
    • Файл для операций ввода-вывода.
    • Файл для пользовательского интерфейса и/или взаимодействия.
    • и так далее.

    Чем больше вы можете разделить различные типы заданий, тем лучше будет организация ваших заголовков.

    • Если у вас есть сомнения, просто спросите себя, можно ли применить те или иные функции к другим программам, отличным по своей природе от вашего нынешнего проекта. Если у вас есть список macros/functions/data, который вы, вероятно, собираетесь использовать в очень разных программах, независимо от набора других, то очень вероятно, что первые должны быть сгруппированы в одном и том же заголовочном файле.

    "object" должен быть описан , как правило, структурой,
    а конкретный и хорошо понятный "operations" (то есть функции), действующие явно на эту структуру .

    Наконец, вы можете написать один или два основных файла, чтобы собрать и связать все файлы, необходимые для вашего проекта.

    В общем, я намерен сохранить файл main.c как можно короче,
    как директор оркестра, контролирующий rest программы.

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

    Вы должны объяснить :

    • какова цель файла,
    • какие данные и функции там определены,
    • как использовать функции,
    • каких результатов можно ожидать,
    • в чем смысл этих результатов,
    • и так далее.

    Если вы попытаетесь выполнить это упражнение, объяснив кому-то другому, что и как должен делать ваш заголовочный файл, вы быстро увидите, что там что-то не имеет смысла.

    Вы должны включить файл заголовка в файл реализации.

    Как правило, вы должны включать как можно меньше заголовочных файлов в заголовочный файл. Включайте только заголовки, необходимые для типов и тому подобного. Затем в файл реализации можно включить все заголовки, необходимые для функций, которые есть в файле заголовка.

    Так что в вашем случае это зависит от того, для чего вам нужен студент и предмет. Если он вам нужен только в файле реализации, вы включаете его туда, и если он вам нужен в заголовке, вы можете включить его туда, и он будет включен в файл реализации, когда вы включите заголовок, соответствующий файлу реализации.

    Похожие вопросы:

    Я делаю проект для класса, и мне нужна помощь, чтобы разбить мою программу на отдельные части. Мой учитель дал нам подсказку, в которой говорилось, какие файлы будут делать то, что нужно, но он не.

    как включить определенные заголовочные файлы по умолчанию, чтобы мне не приходилось вводить их в каждую программу: В dev c++ и code::blocks

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

    Мне нужен совет, как сделать программу perl, которая сможет разбить файл на более мелкие файлы с помощью числовой строки. например: perl split.pl --file=data.txt --numberLine=2 вход data.txt: line1.

    Ссылается CUDA Center Of Excellence, IIT Bombay Я работаю над распараллеливанием сетевого инструмента, но я не могу включить стандартные файлы c, такие как socket.h в kernel, потому что Kernel не.

    Мне удалось написать программу C, которая копирует файлы из одного каталога в другой, и я пытаюсь написать программу, которая копирует каталоги и подкаталоги в другой каталог. Я также смог написать.

    У меня есть программа c++, которая считывает визуализированные изображения из общей памяти и записывает их в канал(mkfifo), так что я могу захватить их с помощью ffmpeg и передавать их в виде живого.

    Я хочу включить и воспроизвести файлы .sid (музыка для чиптюнов C64) в программу cc65. Обычно sid-файлы содержат процедуру воспроизведения, которая начинается с $1000, как мне связать это с моей.

    Читайте также: