Иллюстрированный самоучитель по Architecture .NET

Ограничения на использование управляемых типов в C++

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

  1. Управляемый тип не может быть наследован из неуправляемого типа. С другой стороны, неуправляемый тип не может быть наследован из управляемого типа. Это значит, что структуры иерархий наследственности управляемых и неуправляемых классов всегда отделены друг от друга.
  2. Управляемые типы не могут иметь друзей (т.е. дружественных функций, классов, структур и интерфейсов). Естественно, данное правило не распространяется на неуправляемые классы C++. Это, конечно, может быть и не так важно для многих программистов, ведь многие рассматривают дружественность как нарушение важной концепции объектно-ориентированного программирования, называемой инкапсуляцией. Неуправляемые типы могут иметь друзей, как и классы в традиционном C++; однако неуправляемые типы могут иметь друзей только из числа неуправляемых типов.
  3. В отличие от неуправляемых типов, управляемые не поддерживают множественную наследуемость реализации. Однако как управляемые, так и неуправляемые типы поддерживают множественную наследуемость интерфейсов. Возможность наследовать только одну реализацию является еще одним ограничением, с которым могут смириться многие программисты. Несмотря на то, что традиционный C++ поддерживает множественную наследуемость реализаций, большинство объектно-ориентированных языков (в том числе Java и Smalltalk) ее не поддерживают. Даже модель компонентных объектов Microsoft (COM), которая на двоичном уровне основывается на таблице виртуальных функций в стиле C++, не поддерживает эту возможность.
  4. Управляемый тип может, очевидно, содержать член, который является указателем на управляемый объект. Управляемый тип также может содержать элемент данных, который является неуправляемым объектом или указателем на таковой. С другой стороны, неуправляемый тип не может включать в себя экземпляр управляемого типа или указатель на таковой. Все, что здесь сказано, касается не только указателей, но также и ссылок.
  5. Неуправляемый класс, в котором не указан явно базовый класс, является независимым корневым классом. В то же время, управляемый класс, в котором не указан явно ни один класс в качестве базового, является производным от корневого класса System::Object (Система::Объект).
  6. К объекту, участвующему в сборке мусора (т.е. к экземпляру управляемого класса, который использует ключевое слово _gс (сборщик мусора), а не _value (значение) или _поде), можно получить доступ только посредством указателя (или ссылки) на объект в управляемой динамически распределяемой области памяти. Это является отличием от неуправляемых типов, которые могут содержаться либо непосредственно в переменной типа значения, либо к ним можно получить доступ посредством указателя на неуправляемую динамически распределяемую область памяти.

Перечисленные правила использования управляемых типов в C++ подытожены в предлагаемом примере программы. Комментарии помогут вам понять все эти сложные правила. Если вы откроете проект ManagedAndUnmanagedTypes и попробуете раскомментировать каждый из тех операторов (лучше по одному за один проход), который вызывает ошибку компилятора, вы лучше поймете каждое из правил. Всего лишь щелкните на интересующей вас ошибке в окне Task List (Список задач), а затем нажмите F1 для получения документации, в которой разъясняется суть ошибки. И, конечно, двойной щелчок на ошибке в окне Task List (Список задач) приведет вас к соответствующему оператору в окне редактора исходного кода программы.

Если Вы заметили ошибку, выделите, пожалуйста, необходимый текст и нажмите CTRL + Enter, чтобы сообщить об этом редактору.