Реализация ООП в 1С++

Содержание

Введение

ООП - объектно-ориентированное программирование, является на сегодняшний день одной из самых популярных технологий создания программных средств. Данная разработка направлена на устранение недостатка отсутствия ООП в языке 1С. Как известно, ООП базируется на трех основных принципах: полиморфизм, наследование и инкапсуляция; в данной разработке для возможной технической реализации принципов, были добавлены некоторые языковые средства. Также добавлена возможность строгой проверки типов для параметров методов классов, определяемых пользователем (КОП) и некоторые другие классы для расширения парадигмы ООП.

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

В реализации наследования в ВК (внешней компоненте 1С:Предприятия) 1С++ необходимо определить следующий функционал:

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

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

Работа с компонентой

Состав компоненты

  • 1C:Предприятие 7.7, релизы 14-27, Windows98 OSR2, Windows 2000, Windows XP, Windows 2003, Vista.
  • Файл движка ООП для 1С 1C++.dll, подключается с помощью метода 1С "ЗагрузитьВнешнююКомпоненту(Путь)"
  • Файл определения классов пользователя Defcls.prm, обязан находиться в каталоге информационной базы (ИБ) в которой используются классы, определяемые пользователем компоненты. Синтаксис языка определения классов см. ниже.
  • Файл oxy.ini, который необходимо создать в каталоге BIN 1C:Предприятия для настройки псевдонимов путей к файлам реализации КОП.
  • Файлы реализации классов могут быть как в текстовом формате, так и в формате отчетов с расширением *.ert. Имена файлов и привязки файлов реализации к классам задаются в файле определения Defcls.prm.

Функционал класса

Каждый класс, определенный пользователем (КОП), создается в 1С с помощью метода СоздатьОбъект(ИмяКласса).

Для каждого КОП определен стандартный интерфейс, состоящий из следующих методов:

ПолучитьБазовыйКласс

ПолучитьБазовыйКласс (ИмяБазовогоКласса) / GetBaseClass(strNameOfBaseClass)

Описание:возвращает объект базового класса для класса предка, имя которого передается в качестве строки в параметр метода "ИмяБазовогоКласса". Если объекта базового класса не существует, то метод возвратит 0. Данный метод предназначен для вызова переопределенных методов базовых классов из методов классов наследников и получения/установки атрибутов базовых классов.
Пример:имеются следующие справочники: "Необоротные активы", в котором содержатся общие реквизиты всех необоротных активов предприятия, и справочники - спецификаторы, такие как "Основные средства", "Нематериальные активы", которые, в свою очередь, добавляют специфические реквизиты сущностей к общим реквизитам необоротных активов. Исходя из описанной выше идеологии, мы строим следующую иерархию классов: КОП с рабочим названием "ОС" наследует от классов 1С: справочника "Необоротные активы" и "Основные средства" и переопределяет методы "ВыбратьЭлементы()" и "ПолучитьЭлемент()", т.к у КОП "ОС" базовые классы имеют такие же методы, программист обязан разрешить неоднозначность вызова, воспользовавшись в реализации методов "ВыбратьЭлементы()" и "ПолучитьЭлемент()" класса "ОС" методом ПолучитьБазовыйКласс("Основные средства") для вызова его функций выборки и итераций и ПолучитьБазовыйКласс ("Необоротные активы") для проведения аналогичных операций.

ОтправитьСообщениеМодулюХоз

ОтправитьСообщениеМодулюХоз (КтоОтправил, ВидСообщения, Данные) / SendMessageOwnMod(WhoSend, KindMessage, Data).

Описание:Вызывает предопределенную функцию ОбработкаСобытияОтКласса(отКого, стрСобытие, Данные), реализованную в модуле, вызывающем работающий в данный момент метод КОП, возвращает любое значение, которое будет получено после вызова ОтправитьСообщениеМодулюХоз() в модуле КОП.

ПолучитьПуть

ПолучитьПуть () / GetPathName().

Описание:Возвращает полный путь и название файла, в котором хранится модуль реализации класса.

ПолучитьКонтекстОкружения

ПолучитьКонтекстОкружения () / GetEnvContext()

Возвращаемое значение:
 

Возвращает контекст, из которого получил управление модуль КОП

Описание:

Получить контекст окружения из модуля КОП.

Метод считается устаревшим и оставлен только для совместимости.

Дополнение:

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

Таким образом, мы получаем ситуацию, когда теоретически любая форма может быть изменена в любом классе. И найти, кто же и что нам поменял, можно только глобальным контекстным поиском. Еще прочтите http://itland.ru/forum/index.php?showtopic=12465&st=0&p=65557&#entry65557

ПолучитьСписокПараметров

ПолучитьСписокПараметров (стрИмяМетода) / GetParamsList(strNameOfMeth)

Возвращаемое значение:
 СписокЗначений с параметрами метода.
Описание:Получить список со значениями неявных параметров, переданных в метод, название которого необходимо передать в качестве параметра. Данный метод можно использовать только в теле метода класса, который был определен с последним формальным параметром ":" в файле определения КОП. Более подробное описание см. в пункте 1.3., раздел "Неопределенное количество параметров".

УстановитьПараметрПоИндексу

УстановитьПараметрПоИндексу (стрИмяМетода>,<чИнд>,<нЗнач) / SetOnIndexParams(strNameOfMeth >,<nInd>,<uVal)

Описание:

Метод предназначен для получения ссылки значения неявного параметра по его порядковому номеру и установке нового значения по данной ссылке.

Параметры:
  • стрИмяМетода - Имя метода ссылки на неявные параметры, которого необходимо получить.
  • чИнд - номер неявного параметра, ссылку на который надо получить и заменить
  • нЗнач - Новое значение.
Возврат:

1 - установка успешно произведена, 0 - произошла ошибка при установке

ЗаменитьБазовыйОбъект

ЗаменитьБазовыйОбъект (стрИмяКласса>, <нЗначениеКласса) / ReplaсeBaseObject(strNameClass>, <uValOfClass)

Описание:

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

Параметры:
  • стрИмяКласса - имя базового класса, экземпляр которого мы собираемся заменять.
  • нЗначениеКласса - новый экземпляр базового класса.
Возврат:

1- замена успешно произведена, 0 - произошла ошибка при замене

_ПриОткрытии (устаревший)

_ПриОткрытии / _OnOpen - данный метод устарел и оставлен для совместимости.

_ВыброситьИскл

_ВыброситьИскл (ОбъектИскл) / _Throw(Object)

Описание:формирует исключение с объектом- исключением. Вызов этого метода в модуле КОП прекращает его выполнение и данное исключение передается дальше в другие модули для поиска обработчика исключения (раскрутка стека). Если такой обработчик не будет найден, то выполнение последнего модуля будет прекращено с выводом диагностического сообщения в окно сообщений 1С. Получить объект "Исключение" можно с помощью метода ПолучитьИсключение () дополнительного класса ВыполняемыйМодуль .
Параметры:ОбъектИскл - любой объект 1С.

_ПолучитьКод

_ПолучитьКод () / _GetCode()

Описание:функция, которая должна вернуть строковое представление объекта;

_SQLCreate

_SQLCreate (Value, obMDW)

Описание:

процедура, которую должен реализовать КОП для типизации значения поля выборки объекта ODBCRecordset типом этого КОП (виртуальный конструктор). Должна быть объявлена в модуле с ключевым словом Экспорт. Должна иметь два или меньше параметров. Её вызывает объект ODBCRecordset при получении значения поля выборки, при типизации типом этого КОП.

Параметры:
  • Value - значение поля выборки без типизации;
  • obMDW - статический объект типа MetaDataWork.

ЯвляетсяОбъектом

ЯвляетсяОбъектом (ИмяПроверяемогоТипа) / _IsObject(ИмяПроверяемогоТипа)

Параметры:
  • ИмяПроверяемогоТипа. тип: Строка.
Описание:

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

Возможность использования класса-обработки и как класс и как обработку с формой

Для включения подобной возможности необходимо использовать специальную переменную препроцессора _NOW_PREPARE_CLASS

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

//#if _NOW_PREPARE_CLASS
  // -- данные и методы класса
//#endif //_NOW_PREPARE_CLASS

//#if !_NOW_PREPARE_CLASS
  // -- данные и процедуры формы

  Процедура ПриОткрытии()
  // код открытия формы
  КонецПроцедуры
//#endif  //! _NOW_PREPARE_CLASS

Формат файла определения КОП

Файл определения классов должен быть расположен в одном каталоге с файлом конфигурации и называться Defcls.prm, если файла с таким именем не обнаружено, ВК осуществляет поиск в текущей конфигурации обработки с именем Defcls. Синтаксис языка определения классов следующий:

// - комментарий для программы
класс (class)  имя класса = имя файла класса реализации :
  <имя базового класса>, <имя базового класса> {
Объявления методов класса
};
имя класса
может состоять из любых печатных символов. Внимание! учитывается регистр имени.
имя файла
<Путь>|<#Псевдоним>Имя файла.* | Имя обработки@MD файл реализации класса, если не указан путь, расположенный в каталоге с файлом конфигурации текущей ИБ, в котором реализуются методы класса и определяются атрибуты. Путь может быть относительным и формируется всегда относительно пути расположения конфигурации ИБ, вне зависимости от текущей папки файловой системы. Если указан #Псевдоним пути, то данный псевдоним ищется в файле инициализации компоненты, который должен находиться в каталоге BIN 1С:Предприятия и называться oxy.ini. В данном файле необходимо создать раздел [alias_path], который содержит все псевдонимы путей.

Текст КОП возможно хранить в конфигурации в виде обработок, для этого необходимо указать имя обработки и прибавить окончание @MD, с соблюдением регистра букв у окончания.

Пример файла инициализации компоненты:

[alias_path]
Псевдоним1 = С:\Классы1С_1\
Псевдоним2 = С:\Классы1С_2\

Далее в файле определения пути к классам необходимо написать следующее:

класс МойКласс = #Псевдоним1\ Псевдоним1.ert {};
имя базового класса
базовые классы класса имя класса. Базовые классы могут отсутствовать или их может быть несколько, тогда они разделяются запятой.
объявление методов класса
функции и процедуры. Необязательно определять все функции, а только те, для которых необходимы проверка типов, определение параметров по умолчанию, неявные параметры и передача параметров по значению. (все, что указано в угловых скобочках - опциональные элементы, без них - обязательные элементы)
функции:
<Тип возвращаемого значения> Имя функции (Val | Знач> Тип переменной <Имя переменной = Значение по умолчанию>, <Val | Знач> Тип переменной <Имя переменной>, ...);
процедуры:
void Имя процедуры (Val | Знач> Тип переменной Имя переменной = Значение по умолчанию, <Val | Знач> Тип переменной <Имя переменной>, ...);
Val | Знач
предопределенное слово, означает, что параметр метода передается по значению, т.е. в методе используется копия переданного параметра. (необязательный)

Любой тип - может быть заменен ключевым словом Неопределенный (Undefine), что отключает для данного параметравозвращаемого значения проверку типов. Типом может быть Справочник, что означает возможность передавать в параметр метода справичник любойго вида справочника, (аналогичное поведение для типов Документ, и Регистр, и т.п.) - смысл, аналогичный типу "Справочник" или ГрупповойКонтекст, когда типом параметра может быть контекст любого модуля. (обязательный)

Имя
формального параметра метода. Обязательно должен быть указано при определении значения по умолчанию, во всех остальных случаях - необязателено.
Значение по умолчанию
задается после имени параметра и должно быть одного того же типа, что и тип для данного параметра. Возможные типы: Строка Пар1 = "Значение по умолчанию"; Число Пар1 = 100; Дата Пар1 = '01.01.2002', а также КОП и агрегатные объекты 1С:Предприятия задаются с заключением их в кавычки, например МойКласс ПарКласс = "МойКласс" - по умолчанию параметр ПарКласс будет содержать в теле метода значение экземпляра класса "МойКласс". Значением по умолчанию может быть простое выражение языка 1С, например - значения констант, перечислений, функций без параметров. Например, Дата дПарДата = РабочаяДата(), параметр "дПарДата" примет значение по умолчанию, возвращенное из метода РабочаяДата(). Внимание: при указании в качестве значения по умолчанию "" - тип значения не учитывается. Значения по умолчанию возможно задать только в последних параметрах метода. Также возможно задавать параметры по умолчанию прямо в модулях определения класса, а не в prm-файле, т.е. как в штатном 1С. Но есть ограничения: 1. Приоритет будет у определения в prm-файле 2. Для параметров, определенных в модулях классов, действуют штатные ограничения 1С на параметры по-умолчанию - например, нельзя использовать функции и т.д. 3. Методы с неопределенным числом параметров можно описывать только в прм-файлах.
Неопределенное количество параметров
метод, объявленный с параметром "...", может принимать любое количество параметров во время вызова. Параметры метода, которые определены стандартным образом, называются явными параметрами. Параметры, которые получены в ходе вызова метода в месте определения троеточия и далее за ним, называются неявными. Пример: void Метод1(Строка стрПар1, Число чПар2, ...);, где параметры стрПар1, чПар2 являются явными и при вызове метода в них обязательно необходимо передавать значения их типов. Пример вызова данного метода может выглядеть так: МойКласс.Метод1("{Пар3, Пар4, Пар5}", 200, "Значение параметра 3", "Значение параметра 4", "Значение параметра 5"); , где значения неявных параметров равны следующим строкам "Значение параметра 3", "Значение параметра 4", "Значение параметра 5", количество таких значений в нашем примере равно 3, но оно может быть любым и зависит только от потребностей алгоритма. И в то же время явные параметры стрПар1 и чПар2 в нашем примере, соответственно, получат значения "{Пар3, Пар4, Пар5}" и 200. В реализации метода "Метод1" необходимо написать процедуру со следующей сигнатурой: Процедура Метод(стрПар1, чПар2) //Тело процедуры КонецПроцедуры. Значения неявных параметров можно получить вызвав общий метод класса ПолучитьСписокПараметров (ИмяМетода) (GetParamsList(NameOfMethod)), который возвращает список значений, содержащий неявные значения параметров, переданных в метод. В одном из явных параметров Вы можете передать строку, заключенную в фигурные скобки ({}), и содержащую названия ключей, разделенных запятыми. Данные ключи сопоставляются с неявными параметрами в списке значений, которые в реализации метода класса можно получить, использовав метод списка "Получить(Строка)". В нашем примере таким строковым (явным) параметром является первый параметр метода "стрПар1", значение которого при вызове метода равно "{Пар3, Пар4, Пар5}", что означает - в списке значений неявных параметров содержатся значения "Значение параметра 3", строковый ключ которого равен "Пар3", следующее значение "Значение параметра 4", а ключ для него "Пар4" и т.д.

Примеры:

класс Базовый_1=Base_1.txt
{
  void Метод1(Число пар1, Строка пар2);
  Число Метод2(Число пар1, Дата пар2);
};
класс Производный_1=Derive_1.txt: Базовый_1, Справочник.Спр1, ТаблицаЗначений
{
  void Метод1(Число пар1, Строка пар2); // Данный метод переопределяет метод
    //базового класса
  Число КоличествоСтрок (Число Колич); // В данном случае мы переопределили
    //метод базового класса ТаблицаЗначений и добавили проверку типов. В реализации этого
    //метода можно переадресовать вызов базовому классу
  void Метод3(ОС ОС); // в этот метод мы должны передаем передавать КОП "ОС"
};
класс ОС=OC.txt : Справочник.ОсновныеСредства, Справочник.НематериальныеАктивы
{
  void Метод1(Базовый_1 пар1); // В данном случае в пар1 можно передавать
    //объекты типа "Базовый_1" и его производный класс "Производный_1"
  void Метод2(Производный_1 пар1); // в отличие от предыдущего случае в пар1 мы
    //можем передавать объекты типа "Производный_1", но не "Базовый_1"
  Число ВыбратьЭлементы(Число чРежим);
  Число ПолучитьЭлемент(Число чРежим);
};

Внимание: проверка типов может быть отключена по требованию пользователя, об этом см. ниже.

Формат файлов реализации КОП

Краткое описание синтаксиса

Для каждого КОП необходим отдельный файл реализации (как текстовый, так и отчет 1С), расположенный в каталоге БД или в папке, указанной в определении имени файла класса, либо в папке, указанной в псевдониме пути. С именем класса связывается файл реализации КОП в файле определения Defcls.prm.

Синтаксис языка файла реализации КОП полностью соответствует синтаксису языка 1С:Предприятия, плюс возможно использовать препроцессорные директивы.

Открытые атрибуты КОП определяются как общие переменные в модуле с ключевым словом Экспорт.

Закрытые атрибуты КОП определяются как общие переменные в модуле без ключевого слова Экспорт.

Обращение к методам/атрибутам класса из модуля класса

Обращение к методам компоненты из файла реализации КОП (модуля КОП), таких таким как: `ПолучитьБазовыйКласс`_ , или обращение к виртуальным (экспортным) методам и атрибутам осуществляется через метод вирт() . Пример:

// Реализация метода "Метод1" класса "Производный_1" см. предыдущий пример
Процедура Метод1 (пар1, пар2) Экспорт
  Базовый_1 = вирт().ПолучитьБазовыйКласс("Базовый_1");
  Если Базовый_1 <> 0 Тогда

  КонецЕсли;
КонецПроцедуры

Процедура Метод2 () Экспорт
  вирт().Метод1(1, 2);
КонецПроцедуры

Также есть возможность обращения к виртуальным (экспортным) методам и атрибутам класса без использования виртуальности с помощью метода Я() Например, см. ДинамическиеАтрибуты

Примеры использования вирт() и я() см. по адресам http://www.1cpp.ru/forumfiles/Attachments/1cpp_test_virt_2.rar

или в конфигурации юнит-тестов 1С++ - класс ООПТесты::Тест_Вирт...

Также подробная инфа о вирт() и я() есть в ветке на форуме 1С++ http://www.1cpp.ru/forum/YaBB.pl?num=1207661901/0

Старый вариант, оставленный для совместимости: Обращение к методам компоненты из файла реализации КОП (модуля КОП), таких таким как: ПолучитьБазовыйКласс , осуществляется через Контекст данного модуля. Пример:

// В начале каждого модуля приходится определять закрытую функцию для получения
// контекста. Поэтому лучше пользоваться вирт() !
Функция Этот(Конт) Возврат Конт; КонецФункции

// Реализация метода "Метод1" класса "Производный_1" см. предыдущий пример
Процедура Метод1 (пар1, пар2) Экспорт
  Конт = Этот(Контекст);
  Базовый_1 = Конт.ПолучитьБазовыйКласс("Базовый_1");
  Если Базовый_1 <> 0 Тогда

  КонецЕсли;
КонецПроцедуры

Attention!

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

Перем Конт;
...............
Конт = вирт();
...............

Attention!

или:

Перем Конт;
Функция GetThis(Конт) Возврат Конт; КонецФункции
...............
Конт = GetThis(Контекст);
...............

Если Вы будете использовать такое присваивание, объекты класса, созданные Вами в алгоритмах с помощью конструкции СоздатьОбъект("ИмяКлассаКОП"), никогда не уничтожатся (memory leaks), из-за циклической ссылки на объект внутри модуля реализации КОП. Это замечание также справедливо и для взаимных ссылок, когда один экземпляр класса содержит в себе ссылку на другой, и этот другой, в свою очередь, имеет ссылку на первый.

В каждой реализации класса можно создать процедуры Конструктор () англ. Constructor() и Деструктор () англ. Destructor(), которые вызываются, соответственно, в моменты создания экземпляра класса и его уничтожения (Конструктор() - объект создан, Деструктор() - объект уничтожен). Реализация данных процедур не обязательна.

Работа с базовыми классами

В базовых классах иерархии возможно вызывать открытые методы производных классов (объявленные с ключевым словом "Экспорт"), воспользовавшись для этого контекстом модуля базового класса ( вирт().Метод() ), также с помощью контекста возможно получить название конечного созданного класса ( ТипЗначенияСтр(вирт() ).

Контроль установки/записи атрибутов

Для контроля установки/записи атрибутов необходимо определить предопределенные методы (Процедура) в модуле реализации КОП (слово Экспорт к данным методам применять не обязательно):

  • При чтении атрибута класса вызывается метод ПриПолучении_ИмяАтрибута (ЗначениеАтрибута) англ. OnGet_, где ИмяАтрибута - имя атрибута, определенного в модуле КОП, из которого выполняют считывание, в переменную ЗначениеАтрибута нужно вернуть текущее значение атрибута.
  • При записи в атрибут класса вызывается метод ПриЗаписи_ИмяАтрибута (ЗначениеДляУст) англ. OnWrite_, где ИмяАтрибута - имя атрибута, определенного в модуле КОП, для которого устанавливают значение, передаваемое в параметре ЗначениеДляУст. Атрибут доступен в коде данного метода, и для его установки необходимо присвоить атрибуту полученный параметр метода. Данный метод не изменяет состояние самого атрибута по умолчанию.

Динамические атрибуты класса

  • Динамические атрибуты класса реализуются следующим образом:

    • Класс должен самостоятельно добавить динамическое свойство с помощью встроенного метода КОП ДобавитьДинамическоеСвойство (стрИмяНовогоСвойства)

    Внимание: вызов метода ДобавитьДинамическоеСвойство необходимо производить не через Сам(Контекст) или вирт(), а с помощью спец.метода КОП Я - Я().ДобавитьДинамическоеСвойство. Иначе невозможно будет обратиться к методу базового класса, вызывающего данный код из метода класса-наследника.

    • в классе необходимо определить 2 предопределенных метода класса:

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

      предопределенная функция _ПриЧтенииСвойства (стрИмяСвойства) англ. _OnReadProperty(strNameOfProperty) в параметр "стрИмяСвойства" передается название атрибута, как оно было указано в вызывающем коде. Возвращать данный метод обязан значение считанного атрибута с названием, полученным из параметра метода "стрИмяСвойства".

    • При установке значения атрибута экземпляра класса вызывается предопределенная процедура _ПриЗаписиСвойства (стрИмяСвойства, НовоеЗначениеАтриб), где "стрИмяСвойства" - имя записываемого свойства, а в параметре "НовоеЗначениеАтриб" содержится новое значение атрибута, т.е. правая часть выражения присваивания нового значения свойству класса.

Сериализация экземпляров класса

Экземпляры создаваемых классов можно сохранять в строку, а затем восстанавливать из неё (сериализация КОП). Для этого в классе необходимо определить следующие методы:

  1. IsSerializable() рус. КлассСохраняемый () /Функция/, метод должен возвращать 1, если класс может быть восстановлен или записан в строку.
  2. SaveToString() рус. СохранитьКлассВСтроку () /Функция/, метод должен возвращать строку, по которой потом можно будет восстановить состояние экземпляра класса.
  3. LoadFromString(str) рус. ЗагрузитьИзСтроки (стр) /Процедура/, в данный метод передается строка ранее полученная из метода "СохранитьКлассВСтроку()", по которой можно восстановить состояние класса, существовавшее на момент сохранения. Важно: при подобном создании объекта его встроенный конструктор не вызывается, разработчик класса должен самостоятельно инициализировать полученный объект в методе ЗагрузитьИзСтроки.

Если в классе реализован метод "КлассСохраняемый()", который возвращает значение, не равное 0, и реализован метод СохранитьКлассВСтроку(), то при использовании функции 1С ЗначениеВСтрокуВнутр(ЭкзКласса) вернет строку, сформированную в классе методом "СохранитьКлассВСтроку()".

Для восстановления классов КОП, поддерживающих сериализацию, необходимо, как обычно в 1С, использовать встроенную функцию 1С "ЗначениеИзСтрокиВнутр" Например, СериализованноеПредставление = ЗначениеИзСтрокиВнутр(Объект); Объект = 0; Объект = ЗначениеИзСтрокиВнутр(СериализованноеПредставление);

Возможность универсальной загрузки в любой объект класса:

Для реализации универсального интерфейса загрузки КОП должен определить 5 методов Число СобытиеЗагрузки_НачалоЗагрузки(КолвоКолонок, КолвоСтрок) Число СобытиеЗагрузки_ДобавитьКолонку(ИмяКолонки, НомерТипа) Число СобытиеЗагрузки_ДобавитьДанные(Вектор) Число СобытиеЗагрузки_ОкончаниеЗагрузки() Строка СобытиеЗагрузки_СообщениеОбОшибке()

Необходимо реализовать все 5 методов, иначе будет выдана ошибка. После реализации подобных методов для объектов данного класса можно будет выполнить универсальную выгрузку из различных контейнеров, например, ИТЗ, Вектор/АссоциативныйВектор и др.коллекции - ИТЗ.Выгрузить(ОбъектКОП).

Более подробно см. ветку http://www.1cpp.ru/forum/YaBB.pl?num=1216110955/0

Примеры

Примеры: Иерархия классов выглядит так:

class База = base.ert
{
        void Метод1(); // Этот метод мы не переопределяем, а вызываем здесь
                                                                          // Метод2 производного класса
        void Метод2();
};
class Производный = derive.ert : Тест14_База
{
        void Метод2(); // переопределяем метод базового класса
};

Модуль реализации класса "База":

Процедура Метод2() Экспорт
        Сообщить("База::Метод2");
КонецПроцедуры
Процедура Метод1() Экспорт
        Сообщить("ТипзначенияСтр(Контекст) =
"+ТипзначенияСтр( вирт() )); // получаем название текущего класса
        вирт().Метод2(); // вызываем переопределенный метод
КонецПроцедуры

Модуль реализации класса "Производный":

Процедура Метод2() Экспорт
        Сообщить("Производный::Метод2");
КонецПроцедуры

Модуль:

Сообщить("Создали Производный класс");
копПрозв = СоздатьОбъект("Производный");
копПрозв. Метод1();
Сообщить("Создали База класс");
копБаза = СоздатьОбъект("База");
копБаза. Метод1();

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

Создали Производный класс
Производный
Производный::Метод2
Создали База класс
База
База::Метод2

В одном модуле можно хранить код нескольких классов. Для этого необходимо код каждого класса заключить в следующие скобки:

//# ClassBegin <ClassName1>;
Перем ПеременнаяКласса1;
Процедура Конструктор()
        .........
//# ClassEnd <ClassName1>;



//# ClassBegin <ClassName2>;
Перем ПеременнаяКласса2;
Процедура Конструктор()
        .........
//# ClassEnd <ClassName2>;

Где вместо <ClassName1> нужно указать имя класса (без угловых скобок). Наличие пробела после # и ClassBegin обязательно. Также обязательно наличие ; сразу после имени класса. Ограничения:

  • Текст одного класса обязательно должен идти одним куском.
  • Штатный синтаксис-контроль подобных модулей в Конфигураторе не работает без плагина Visual1C++.
  • Формирование ALS-файлов для таких классов - невозможно.

Препроцессор

Директивы препроцессора 1С++ могут быть в файлах объявления интерфейсов классов (Defcls.prm), в файлах реализации КОП и во всех модулях 1С, кроме модуля глобального модуля и модулей внешних обработок/отчетов. Символы препроцессора, объявленные в файле объявления класса, действительны в области видимости модулей реализации класса, т.е. доступны в файлах реализации КОП. Внимание: из-за раздельной интерпретации файла Defcls.prm и файлов реализации КОП изменения, определения и отключение символов препроцессора осуществляются независимо. Работа препроцессора гарантируется в следующей последовательности: сначала обрабатывается файл Defcls.prm, затем в неопределенной последовательности обрабатываются файлы реализации КОП.

//#if symbol [operator symbol]

Если символ определен, что равнозначно "истине", или символы, объединённые логическими операторами дают в результате "истину", то код, заключенный между директивами //#if и //#elif или //#else или //#endif, буден включен на выполнение. Symbol - это символ, который будет тестироваться на определенность ранее директивой //#define. Перед символом можно использовать знак ! (логическое отрицание). Operator:

=  (равно);
!=  (не равно);
&   (И);
\|   (ИЛИ);

тело с кодом, открытое директивой //#if, должно закрываться директивами //#elif , //#else, //#endif;

//#else
директива, тело которой получает управление, если выражение равно "ложь" в предшествующих ей директивах //#if или //#elif. Тело с кодом должно заканчиваться директивой //#endif;
//#elif symbol [operator symbol]
директива, управление на которую передается, если в предыдущих директивах //#elif и //#if была получена "ложь". Проверяются условия указанные symbol [operator symbol]... и, если получена "истина", код заключенный в блоке между //#elif, и следующим за ним директивой //#elif или #else или //#endif, включается в код модуля КОП. Описание symbol [operator symbol]... см. у директивы //#if;
//#define symbol
определяет символ условной компиляции, использование этого символа в условных директивах даст "истину", с условием отсутствия снятия этого символа ранее директивой //#undef;
//#undef symbol
убирает определенный ранее символ. Символ используется для условной интерпретации кода в директивах //#if, //#elif, //#else;
//#warning text
выводит "text" в окно сообщений 1С. Примечание: в Defcls.prm данная директива отключена;
//#error text
останавливает выполнение кода программы в этом месте с выводом "text" в окно сообщений 1С. Примечание: в Defcls.prm данная директива отключена;
//#preprocessor off
данная директива должна располагаться в первой строке модуля и служит для выключения препроцессорной обработки кода модуля.
//#exinfo
данная директива может быть использована только в модулях реализации КОП. Директива выводит информацию пользователю о месте вызова метода, в котором она расположена, и строку кода, который осуществил вызов метода. В основном используется в отладочных целях.
#include "<#alias></pathname/>namefile.ext"
директива служит для вкладывания других файлов определений в основной файл проекта (ИБ) defcls.prm. В пути к файлу может быть использован псевдоним, определенный в oxy.ini, относительный путь или полный путь к файлу. Каталогом по умолчанию считается каталог ИБ. Расширение файла может быть txt, prm - обычные текстовые файлы и ert - модуль отчета 1С
#curmeth
директива выводит на экран текущий исполняемый метод класса и его параметры с актуальными значениями и типами в месте появления данной директивы. Примечание: в Defcls.prm данная директива отключена.

Отладка классов 1C++

Для отладки модулей классов необходимо выполнить следующие действия:

  1. В настройках компоненты 1С++ нажать кнопку "Отладка;
  2. Отладка возможна только для классов, хранящихся во внешних ert-файлах или встроенных в конфигурацию в виде обработок;
  3. Если модуль класса расположен в текстовом файле, то следует сохранить его в модуле отчета;
  4. Форма отчета, в котором хранится модуль класса, обязана иметь хотя бы один диалоговый элемент.

ВНИМАНИЕ: Рекомендуется в клиентском режиме 1С:Предприятия выключать режим "Отладки".

  1. Возможна проблема: Глобальные объекты, созданные в режиме отладки, не дают закрыть 1С!
Например, если в глобальном модуле написано
  Перем глОбъект;
  Процедура ПриНачалеРаботыСистемы()
      ЗагрузитьВнешнююКомпоненту("1cpp.dll");
      // а теперь включить режим отладки
        глОбъект = СоздатьОбъект("КОП");
      // объект создан в режиме отладки, его отладочная форма видна на экране
  КонецПроцедуры  // ПриНачалеРаботыСистемы

  После запуска такой конфигурации в режиме отладки
  1С невозможно закрыть стандартными средствами :(

  К сожалению, не помогает и явный сброс объекта
  Процедура ПриЗавершенииРаботыСистемы()
      глОбъект = 0;
  КонецПроцедуры  // ПриЗавершенииРаботыСистемы
  До этой процедуры дело просто не доходит :(

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

Настройка 1C++

Настройка компоненты осуществляется с помощью настройки параметров 1С, Сервис --> Параметры ... --> Закладка "Настройка 1C++". Данная закладка появляется только после загрузки компоненты методом 1С ЗагрузитьВнешнююКомпоненту.

На данной закладке присутствуют три флажка в виде кнопок: "Проверка типов" и "Оптимизация", "Отладка":