Public ref class c что это
Что значит public ref class
В чем отличие ref class от value class, где какой следует использовать?
САБЖ, мало по мало изучаю C++/CLI.. В голове каша, хотелось бы как то фундаментально осмыслить и.
Конструктор с несколькими параметрами в ref class
Простите, что не пишу в C++/CLI, просто там никого нет онлайн, и ждать ответа пришлось бы на.
Замена friend-операторов для ref class
Если в ref-классе написать friend operator+(double _Left, MyClass ^_Right), высвечивается ошибка.
В C++/CLI существуют ссылочные классы (ref class) и классы значений (value class). Модификаторы определяют уровень доступа к классу.
Из MSDN:
Все типы и члены типов имеют уровень доступности, который определяет возможность их использования из другого кода в сборке разработчика или других сборках. Можно использовать следующие модификаторы доступа для указания доступности типа или члена при объявлении этого типа или члена.
public
Доступ к типу или члену возможен из любого другого кода в той же сборке или другой сборке, ссылающейся на него.
private
Доступ к типу или члену можно получить только из кода в том же классе или структуре.
protected
Доступ к типу или элементу можно получить только из кода в том же классе или структуре, либо в производном классе.
internal
Доступ к типу или члену возможен из любого кода в той же сборке, но не из другой сборки.
static ref class, глобальный статичный класс
Добрый день, столкнулся с проблемой создания глобального гласа, который уже был бы реализован при.
Конструктор неявного преобразования из double и System::String ^ в ref class
Кто знает, как это реализовать, чтобы, например, был возможен код: public ref class MyClass <.
Что значит Public без типов данных?
Вот пример с типом данных: public bool SameAs <> тут тип данных bool, но в следующем примере он.
Что такое ref class
Здравствуйте, господа программисты! Не могли бы вы мне скинуть ссылочку на какой-нибудь сайт.
Ref classes and structs (C++/CX)
The C++/CX supports user-defined ref classes and ref structs, and user-defined value classes and value structs. These data structures are the primary containers by which C++/CX supports the Windows Runtime type system. Their contents are emitted to metadata according to certain specific rules, and this enables them to be passed between Windows Runtime components and Universal Windows Platform apps that are written in C++ or other languages.
A ref class or ref struct has these essential features:
It must be declared within a namespace, at namespace scope, and in that namespace it may have public or private accessibility. Only public types are emitted to metadata. Nested public class definitions are not permitted, including nested public enum classes. For more information, see Namespaces and Type Visibility.
It may implement one or more interface classes or interface structs.
It may inherit from one base class, and base classes themselves have additional restrictions. Inheritance in public ref class hierarchies has more restrictions than inheritance in private ref classes.
It may not be declared as generic. If it has private accessibility, it may be a template.
Its lifetime is managed by automatic reference counting.
Declaration
The following code fragment declares the Person ref class. Notice that the standard C++ std::map type is used in the private members, and the Windows Runtime IMapView interface is used in the public interface. Also notice that the «^» is appended to declarations of reference types.
Implementation
This code example shows an implementation of the Person ref class:
Usage
The next code example shows how client code uses the Person ref class.
Memory management
You allocate a ref class in dynamic memory by using the ref new keyword.
By definition, a ref class has reference semantics. When you assign a ref class variable, it’s the handle that’s copied, not the object itself. In the next example, after assignment, both myClass and myClass2 point to the same memory location.
When a C++/CX ref class is instantiated, its memory is zero-initialized before its constructor is called; therefore it is not necessary to zero-initialize individual members, including properties. If the C++/CX class derives from a Windows Runtime C++ Library (WRL) class, only the C++/CX derived class portion is zero-initialized.
Members
A ref struct is the same as a ref class, except that by default its members have public accessibility.
A public ref class or ref struct is emitted in metadata, but to be usable from other Universal Windows Platform apps and Windows Runtime components it must have at least one public or protected constructor. A public ref class that has a public constructor must also be declared as sealed to prevent further derivation through the application binary interface (ABI).
Public members may not be declared as const because the Windows Runtime type system does not support const. You can use a static property to declare a public data member with a constant value.
Public ref classes that have type parameters are not permitted. User-defined generic ref classes are not permitted. A private, internal, or protected private ref class may be a template.
Destructors
In C++/CX, calling delete on a public destructor invokes the destructor regardless of the object’s reference count. This behavior enables you to define a destructor that performs custom cleanup of non-RAII resources in a deterministic manner. However, even in this case, the object itself is not deleted from memory. The memory for the object is only freed when the reference count reaches zero.
If a class’s destructor is not public, then it is only invoked when the reference count reaches zero. If you call delete on an object that has a private destructor, the compiler raises warning C4493, which says «delete expression has no effect as the destructor of does not have ‘public’ accessibility.»
Ref class destructors can only be declared as follows:
public and virtual (allowed on sealed or unsealed types)
protected private and non-virtual (only allowed on unsealed types)
private and non-virtual (allowed only on sealed types)
No other combination of accessibility, virtualness, and sealedness is allowed. If you do not explicitly declare a destructor, the compiler generates a public virtual destructor if the type’s base class or any member has a public destructor. Otherwise, the compiler generates a protected private non-virtual destructor for unsealed types, or a private non-virtual destructor for sealed types.
The behavior is undefined if you try to access members of a class that has already had its destructor run; it will most likely cause the program to crash. Calling delete t on a type that has no public destructor has no effect. Calling delete this on a type or base class that has a known private or protected private destructor from within its type hierarchy also has no effect.
Inheritance
Platform::Object is the universal base class for all ref classes. All ref classes are implicitly convertible to Platform::Object and can override Object::ToString. However, the Windows Runtime inheritance model not intended as a general inheritance model; in C++/CX this means that a user-defined public ref class cannot serve as a base class.
If you are creating a XAML user control, and the object participates in the dependency property system, then you can use Windows::UI::Xaml::DependencyObject as a base class.
A private base ref class is not required to derive from an existing unsealed class. If you require an object hierarchy to model your own program structure or to enable code reuse, then use private or internal ref classes, or better yet, standard C++ classes. You can expose the functionality of the private object hierarchy through a public sealed ref class wrapper.
A ref class that has a public or protected constructor in C++/CX must be declared as sealed. This restriction means that there is no way for classes that are written in other languages such as C# or Visual Basic to inherit from types that you declare in a Windows Runtime component that’s written in C++/CX.
Here are the basic rules for inheritance in C++/CX:
Ref classes can inherit directly from at most one base ref class, but can implement any number of interfaces.
If a class has a public constructor, it must be declared as sealed to prevent further derivation.
For ref classes, only public inheritance is supported.
The following example shows how to expose a public ref class that derives from other ref classes in an inheritance hierarchy.
Кратко и быстро разбираемся с C++ CLI
Так сложилось, что по мере рабочей необходимости мне приходится интенсивно использовать C++/CLI и, соответственно, довольно часто объяснять новичкам, что это, как работает, как использовать и, зачем вообще надо. Так что со временем появилось желание написать статью с обзором языка, ответами на некоторые распространенные вопросы и показать места, где могут удачно лечь грабли.
Что это?
К тому же, в этом синтаксисе не было отличий между указателем на нативный тип и на управляемый (в обоих случаях использовалась «*»), не было ключевого слова для обозначения нулевого указателя и прочее. Это и толкнуло Microsoft на создание новой ревизии языка, о которой и пойдет речь в данной статье.
Замечание: эти две версии синтаксиса называются, как ни странно, «old syntax» и «new syntax», и какую именно использовать можно выбирать в настройках компиляции проекта. Впрочем, при создании новых сборок лучше использовать новый синтаксис, так как старый помечен как устаревший и просто плох.
Зачем нужно?
2) Можно вызывать уже написанный на плюсах код. Действительно, поскольку у нас остались все возможности обычного C++, то можно создавать управляемые обертки для существующих классов на нативных плюсах. Это дает намного большие возможности по вызову неуправляемого кода, нежели PInvoke, который с классами работать не умеет.
Как работает?
Все очень просто. При компиляции кода на С++/СLI получается сборка, содержащая как MSIL код, так и машинные команды, в которые превратились строки, написанные на «чистых» плюсах. «Но как же быть с кроссплатформеностью?» — спросите вы, и будете совершенно правы. Никак. В частности, это означает, что не получится собрать один и тот же бинарник для 32 и 64 битных версий (собрать все под «Any CPU»). Такова расплата за использование всех возможностей С++. Естественно, это относится к тому варианта, когда используется микс из управляемого и неуправляемого кода. Всего есть несколько вариантов компиляции:
• /clr — поддержка управляемого и нативного кода с использованием нового синтаксиса.
• /сlr:pure — нативный код не поддерживается. Однако при этом можно использовать небезопасный ) код, в той мере, как это можно делать, к примеру, в С#-сборках при использовании директивы unsafe.
• /clr:safe — Только управляемый безопасный код. Аналог — компиляция C#-сборки без использования unsafe.
• /clr:oldSyntax — аналог /clr, только используется старый синтаксис.
Как выглядит?
Вот примеры сравнения основных конструкций для С# и C++/CLI.
Объявление класса
public sealed class Class1 : Class2
public ref class Class1 sealed : Class2
Объявление структуры
public struct Class1 : IEquatable
public value class Class1 : IEquatable
Объявление интерфейса
public interface ISomeInterface
public interface class ISomeInterface
Объявление перечисления
Создание управляемого объекта
В C++/CLI для обозначения ссылок на управляемые объекты используется «^» вместо «*». Это очень удобно чтобы различать объекты, которые потом надо удалить и те, которые не надо. Также при создании локального ссылочного объекта можно использовать семантику стека:
Object obj();
Это имеет смысл либо при использовании объектов, реализующих IDisposable (речь об этом пойдет позже) либо для value-типов. Заметим, что в плане хранения и использования value-типов С++/CLI дает большую свободу, чем C#, поскольку программист может сам выбирать — использовать ссылку или значение. Таким образом вполне можно в некоторых ситуация сэкономить на количестве boxing/unboxing операций.
Создание управляемого массива
Неуправляемые массивы при этом создаются как обычно.
Передача параметров в метод
void Method( int byValue, ref int byRef, out int outValue);
void Method( int byValue, int %byRef, [ out ] int %outValue);
Переопределение метода
Реализация шаблона IDisposable
protected virtual void Dispose( bool disposing)
<
if (disposing)
<
//release managed resources
>
//release unmanaged resources
>
Class1()
<
//release managed resources
//Аналог финализатора
!Class1()
<
//release unmanaged resources
>
>
Что осталось за кадром?
Понятно, что в одну статью все поместить не удалось. Не рассмотренными остались такие вопросы как:
• Синтаксис делегатов, свойств, методов расширения, foreach и прочее
• Жонглирование из управляемого в неуправляемый и обратно объектами, массивами и прочим
• Что поддерживается и нет из того, что есть в С# и в обычном C++
• Особености компиляции приложений со сборками С++/CLI
• Вопросы производительности. Когда и в чем можно получить выигрыш? Где можно внезапно потерять?
Что почитать?
Заключение
Универсальные классы (C++/CLI)
Универсальный класс объявляется в следующем формате:
Синтаксис
Remarks
В приведенном синтаксисе используются следующие элементы.
attributes
(Необязательно) Дополнительные описательные данные. Дополнительные сведения об атрибутах и классах атрибутов см. в разделе «Атрибуты».
class-key
Либо class **** typename
type-parameter-identifier(s) — разделенный запятыми список идентификаторов, определяющих имена параметров типа.
constraint-clauses
Список (не разделенный запятыми) предложений where, определяющих ограничения параметров типа. Имеет следующий вид:
где Type-Parameter-идентификатор : constraint-List .
identifier
Имя универсального класса — любой допустимый идентификатор C++.
модификаторы
(Необязательно) Допустимые модификаторы: sealed и abstract.
base-list
Список, содержащий один базовый класс и любые реализованные интерфейсы, разделенные запятыми.
class-body
Тело класса, содержащее поля, функции-члены и т. д.
Базовый класс и базовые интерфейсы не могут быть параметрами типа. Однако базовый класс может содержать параметр типа в качестве аргумента, как показано в следующем примере.
Конструкторы и деструкторы выполняются один раз для каждого экземпляра объекта (как обычно); статические конструкторы выполняются один раз для каждого сконструированного типа.
Поля в универсальных классах
В этом разделе показано использование экземпляра и статических полей в универсальных классах.
Переменные экземпляра
Переменные экземпляра универсального класса могут иметь типы и инициализаторы переменных, в том числе любые параметры типа из включающего класса.
Пример. различные универсальные классы
Статические переменные
При создании универсального типа создаются новые экземпляры всех статических переменных и выполняется любой статический конструктор для данного типа.
Статические переменные могут использовать любые параметры типа из включающего класса.
Пример. Использование статических переменных
В следующем примере показано использование статических полей и статического конструктора в универсальном классе.
Методы в универсальных классах
Методы в универсальных классах сами могут быть универсальными; неуниверсальные методы будут неявно параметризованы параметром типа класса.
Для методов в универсальных классах применяются следующие специальные правила.
Методы в универсальных классах могут использовать параметры типа в качестве параметров, возвращаемых типов или локальных переменных.
Методы в универсальных классах могут использовать открытые или закрытые сконструированные типы в качестве параметров, возвращаемых типов или локальных переменных.
Неуниверсальные методы в универсальных классах
Методы в универсальных классах, не имеющие дополнительных параметров типа, обычно называются неуниверсальными, хотя неявно параметризуются включающим универсальным классом.
В сигнатуре неуниверсального метода может присутствовать один или несколько параметров типа включающего класса непосредственно или в виде открытого сконструированного типа. Пример:
void MyMethod(MyClass x) <>
Эти параметры типа также могут использоваться в теле таких методов.
Пример. объявление неуниверсального метода
Универсальные методы в универсальных классах
Универсальные методы можно объявлять в универсальных и неуниверсальных классах. Пример:
Пример. объявление универсальных и неуниверсальных методов
Неуниверсальный метод является, однако, универсальным в том смысле, что он параметризуется параметром типа класса, но не содержит дополнительных параметров типа.
Все типы методов в универсальных классах могут быть универсальными, включая статические, экземплярные и виртуальные.
Пример. объявление и использование универсальных методов
В приведенном ниже примере показано объявление и использование универсальных методов в универсальных классах.
Использование вложенных типов в универсальных классах
Так же как и в обычных классах, в универсальном классе можно объявлять разные типы. Объявление вложенного класса неявно параметризуется параметрами типа объявления внешнего класса. Таким образом, для каждого сконструированного внешнего типа определяется отдельный вложенный класс. Например, в объявлении
Как и в случае с универсальными методами, в универсальных классах дополнительные параметры типа можно задавать для вложенных типов. Если во внутреннем и внешнем классах используются одинаковые имена параметров типа, параметр внутреннего типа скрывает параметр внешнего типа.
Поскольку обратиться к параметру внешнего типа невозможно, компилятор в этой ситуации выдает предупреждение.
Пример: сборка и чтение связанного списка
В приведенном ниже примере показано создание и чтение связанного списка с помощью вложенных типов в универсальных классах.
Свойства, события, индексаторы и операторы в универсальных классах
Свойства, события, индексаторы и операторы могут использовать параметры типа включающего универсального класса в качестве возвращаемых значений, параметров или локальных переменных, например, если ItemType является параметром типа класса:
Сами свойства, события, индексаторы и операторы не могут быть параметризованы.
Пример: объявление свойства экземпляра
В следующем примере показано объявление свойства экземпляра в универсальном классе.
Пример: универсальный класс с событием
В следующем примере показан универсальный класс с событием.
Универсальные структуры
Правила объявления и использования универсальных структур — те же, что и для универсальных классов, за исключением различий, описанных в справочнике по языку Visual C++.
Пример. объявление универсальной структуры
Классы и структуры ссылки (C++/CX)
C++/CX поддерживает определяемые пользователем ссылочные классы и Ссылочные структуры, а также пользовательские классы значений и структуры значений. эти структуры данных являются основными контейнерами, по которым C++/cx поддерживает систему типов среда выполнения Windows. их содержимое передается в метаданные в соответствии с определенными правилами, и это позволяет передавать их между компонентами среда выполнения Windows и универсальная платформа Windows приложениями, написанными на C++ или на других языках.
Класс ссылки и структура ссылки имеют следующие основные особенности:
они могут реализовывать один или несколько классов интерфейсов или структур интерфейсов;
они могут наследовать одному базовому классу, а на сами базовые классы налагаются дополнительные ограничения. Наследование в иерархиях открытых классов ссылок имеет больше ограничений, чем наследование закрытых классов ссылок;
они не могут объявляться как универсальные. Если они имеют закрытый доступ, они могут быть шаблонами;
Их время жизни управляется автоматическим подсчетом ссылок.
Объявление
Реализация
Использование
Также можно также объявить локальную переменную класса ссылки с помощью семантики стека. Поведение такого объекта аналогично поведению стековой переменной, несмотря на то что память все же выделяется динамически. Важное отличие заключается в том, что нельзя присвоить отслеживаемую ссылку (%) переменной, объявленной с использованием семантики стека: таким образом гарантируется, что счетчик ссылок уменьшается до нуля, когда выполняется выход из функции. В этом примере показаны базовый класс ссылки Uri и функция, в которой он используется с семантикой стека:
Управление памятью
Класс ссылки выделяется в динамической памяти с помощью ref new ключевого слова.
По определению класс ссылки имеет семантику ссылки. Когда вы присваиваете значение переменной класса ссылки, копируется не сам объект, а его дескриптор. В следующем примере после операции присваивания оба объекта myClass и myClass2 указывают на одно и то же расположение в памяти.
Когда создается экземпляр класса ссылки C++/CX, его память перед вызовом конструктора инициализируется нулями, поэтому такая инициализация для отдельных членов, включая свойства, не требуется. Если класс C++/CX является производным от класса библиотеки C++ для среды выполнения Windows (WRL), инициализация нулями осуществляется только для области производного класса C++/CX.
Элементы
Структура ref аналогична ссылочному классу, за исключением того, что ее члены по умолчанию имеют public доступ.
public ссылочный класс или структура ссылки создаются в метаданных, но их можно использовать из других универсальная платформа Windows приложений и среда выполнения Windows компонентов, которые должны иметь по крайней мере один открытый или защищенный конструктор. Открытый класс ссылки, имеющий открытый конструктор, также должен быть объявлен как sealed для предотвращения дальнейшего наследования через двоичный интерфейс приложения (ABI).
При определении открытого класса или структуры ссылок компилятор применяет необходимые атрибуты к классу и сохраняет эти сведения в файле WinMD приложения. однако при определении открытого незапечатанного класса ссылки вручную примените Windows::Foundation::Metadata::WebHostHidden атрибут, чтобы класс не был видимым для универсальная платформа Windows приложений, написанных на JavaScript.
Открытые классы ссылки, имеющие параметры-типы, не допускаются. Определяемые пользователем универсальные классы ссылок не допускаются. Класс ссылки с атрибутами private, internal или protected private может быть шаблоном.
Деструкторы
В C++/CX вызов метода delete в открытом деструкторе вызывает деструктор независимо от счетчика ссылок объекта. Это позволяет определить деструктор, который будет выполнять пользовательскую очистку ресурсов, не относящихся к RAII, детерминированным образом. Однако даже в этом случае сам объект не удаляется из памяти. Память для объекта освобождается, только когда число ссылок достигает нуля.
Если деструктор класса не является общим, он вызывается только в случае, когда число ссылок достигает нуля. При вызове delete для объекта, имеющего закрытый деструктор, компилятор выдает предупреждение C4493, что говорит о том, что выражение delete не действует, так как деструктор не имеет модификатора public.
Деструкторы классов ссылок можно объявлять только следующим образом:
открытый и виртуальный (допускается только для запечатанных и незапечатанных типов);
защищенный закрытый и невиртуальный (допускается только для незапечатанных типов);
закрытый и невиртуальный (допускается только для запечатанных типов).
Никакие другие сочетания режимов доступа, виртуальности и запечатанности не допускаются. Если деструктор явно не объявлен, компилятор создает открытый виртуальный деструктор, если у базового класса типа или любого из его членов имеется открытый деструктор. В противном случае компилятор создает защищенный закрытый невиртуальный деструктор для незапечатанных типов и закрытый невиртуальный деструктор для запечатанных типов.
При попытке обращения к членам класса, для которого уже запускался деструктор, поведение будет неопределенным; это наиболее вероятная причина сбоя программы. При вызове delete t для типа, у которого нет открытого деструктора, ничего не происходит. Вызов delete this для типа или базового класса, который имеет известный private деструктор или protected private из его иерархии типов, не оказывает никакого влияния.
Наследование
Platform::Object является универсальным базовым классом для всех классов ссылок. Все классы ссылок неявно преобразуются в Platform::Object и могут переопределять Object::ToString. однако модель наследования среда выполнения Windows не предназначена как общая модель наследования. в C++/CX это означает, что определяемый пользователем открытый класс ссылки не может служить базовым классом.
Закрытый базовый класс ссылки не требуется для наследования от существующего незапечатанного класса. Если требуется, чтобы иерархия объектов моделировала собственную структуру программы или обеспечивала повторное использование кода, используйте закрытые или внутренние классы ссылок, а лучше стандартные классы C++. Доступ к функциональности закрытой иерархии объектов можно реализовать с помощью оболочки открытого запечатанного класса ссылки.
Класс ссылки, имеющий открытый или защищенный конструктор в C++/CX, должен быть объявлен как Sealed. это ограничение означает, что для классов, написанных на других языках, таких как C# или Visual Basic, не существует способа наследования от типов, объявляемых в среда выполнения Windows компоненте, написанном на C++/CX.
Ниже приведены основные правила наследования в C++/CX.
классы ссылок могут напрямую наследовать не более чем от одного базового класса, но могут реализовывать любое количество интерфейсов;
если у класса имеется открытый конструктор, он должен объявляться как запечатанный, чтобы запретить его дальнейшее наследование;
для классов ссылок поддерживается только открытое наследование.
В следующем примере показано, как предоставлять доступ к открытому классу ссылки, производному от других классов ссылки в иерархии наследования.