Получить родительский COM-объект из дочернего COM-объекта

Интерфейс ID3D12GraphicsCommandList наследуется от < a href="https://docs.microsoft.com/en-us/windows/desktop/api/d3d12/nn-d3d12-id3d12commandlist" rel="nofollow noreferrer">ID3D12CommandList. Итак, если у меня есть объект ID3D12GraphicsCommandList, как мне получить соответствующий объект ID3D12CommandList?

  1. Будет ли работать приведение типов?
    ID3D12GraphicsCommandList *gcl = ...;
    ID3D12CommandList *cl = (ID3D12CommandList*)gcl;
  1. Будет ли работать QueryInterface?
    ID3D12GraphicsCommandList *gcl = ...;
    ID3D12CommandList *cl;
    HRESULT result = ID3D12GraphicsCommandList_QueryInterface(gcl,
                                                              &IID_ID3D12CommandList,
                                                              (void**)&cl);
  1. Нужно ли мне делать что-то еще?

Спасибо.


person marked-off-topic    schedule 01.07.2021    source источник
comment
он у вас уже есть. ничего не нужно делать,   -  person RbMm    schedule 01.07.2021
comment
@RemyLebeau - даже cl = gcl не нужно. gcl уже ID3D12CommandList*   -  person RbMm    schedule 01.07.2021
comment
@RbMm Мне нужно сохранить gcl внутри ID3D12CommandList [] (массив), поэтому мне нужно преобразовать в cl.   -  person marked-off-topic    schedule 01.07.2021
comment
@RbMm, поскольку вопрос помечен как C, а не C++, проблема немного сложнее. То, что вы говорите, верно для C++, но C не имеет классов или наследования, поэтому доступ к базовому интерфейсу из указателя на производный интерфейс требует немного больше работы. Итак, я бы придерживался использования Queryinterface(), чтобы упростить задачу и не беспокоиться о деталях.   -  person Remy Lebeau    schedule 01.07.2021
comment
@RemyLebeau Просто для подтверждения, QueryInterface можно использовать и для доступа к родителям? (Потому что я когда-либо использовал его только для доступа к детям)   -  person marked-off-topic    schedule 01.07.2021
comment
@marked-off-topic Queryinterface() можно использовать для доступа к любому интерфейсу, который реализует базовый объект.   -  person Remy Lebeau    schedule 01.07.2021
comment
QueryInterface следует понимать буквально: он спрашивает объект за указателем интерфейса, реализует ли он какой-либо данный интерфейс. Этот интерфейс может быть вверх или вниз по цепочке наследования или вообще не быть частью наследования. Типичным примером являются двойные интерфейсы, где IDispatch обычно реализован как аналог интерфейса(ов) на основе VTable. Так что да, использование QueryInterface - правильный путь.   -  person IInspectable    schedule 01.07.2021
comment
не замечайте, что это c (не c++), в этом случае просто используйте приведение a[i] =(ID3D12CommandList*)gcl. не нужно вызывать QueryInterface, потому что у вас уже есть указатель на ID3D12CommandList*   -  person RbMm    schedule 01.07.2021
comment
@rbm Это делает предположения о расположении объектов, которые не поддерживаются правилами COM (или nano-COM, используемыми DirectX).   -  person IInspectable    schedule 01.07.2021
comment
@IInspectable _ нет, здесь нет никаких предположений о расположении объектов. потому что ID3D12GraphicsCommandList унаследовал от ID3D12CommandList   -  person RbMm    schedule 01.07.2021
comment
Наследование интерфейса @rbm COM не требует какой-либо конкретной реализации на уровне языка. Любая конкретная реализация интерфейса может свободно использовать любой заданный макет объекта, включая макет объекта, который, по совпадению, не потребует настройки указателя. Хотя на самом деле вы ошибались в прошлом, даже доказуемо ошибались, и даже не считали, что ошибаетесь. Почему сегодня должно быть иначе?   -  person IInspectable    schedule 01.07.2021
comment
@IInspectable - виртуальная таблица для интерфейса ID3D12GraphicsCommandList, содержащая виртуальную таблицу ID3D12CommandList в начале, и любые методы ID3D12CommandList могут быть вызваны этим vtable.   -  person RbMm    schedule 01.07.2021
comment
@marked-off-topic это часть C SO. Не С++. И не Директ 3D. Реализация COM находится на языке C. Не могли бы вы задать вопрос COM по коду C? Поддерживается IDL, пожалуйста.   -  person Chef Gladiator    schedule 01.07.2021
comment
@che Это это код C. IDL также не требуется, поскольку Windows SDK предоставляет предварительно сгенерированные заголовки. Если вам интересно увидеть IDL, d3d12.idl также поставляется с SDK. Этот вопрос также относится к DirectX, поскольку DirectX использует производную COM, иногда называемую облегченной COM или nano-COM. Он следует семантическим правилам COM, но не использует (большую часть) инфраструктуру COM, предоставляемую ОС.   -  person IInspectable    schedule 01.07.2021
comment
Просто потрясающе, конечно, непонятна элементарная вещь - если мы можем вызвать любой метод из I2 (унаследованный от I1) с указателем p - мы можем вызвать любой метод из I1 с тем же указателем p - просто потому, что любой метод из I1 - будет метод I2..   -  person RbMm    schedule 01.07.2021


Ответы (3)


  1. Будет ли работать приведение типов?

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

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

  1. Будет ли работать QueryInterface?

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

  1. Нужно ли мне делать что-то еще?

Нет, не совсем, если вы следуете правилам COM. Одна деталь часто упускается из виду: успешный вызов QueryInterface увеличивает счетчик ссылок на интерфейс, так что вам придется Release каждый интерфейс, возвращенный вызовом QueryInterface.


Почему кастинг небезопасен

Итак, если IDerived наследуется от IBase, то почему очевидный выбор, преобразование указателя из IDerived* в IBase*, не является допустимым? TL; DR, потому что COM не предоставляет гарантий, которые сделали бы это действительным.

Требования COM ошеломительно минималистичны. На самом деле,

Единственное языковое требование для СОМ заключается в том, что код создается на языке, который может создавать структуры указателей и явно или неявно вызывать функции через указатели.

Это позволяет использовать широкий спектр языков программирования для реализации COM-интерфейсов. Обратной стороной этого является то, что COM предлагает очень мало гарантий в отношении того, как ABI сопоставляется с языком- уровневые конструкции. Это особенно верно для наследования интерфейса:

Наследование в COM не означает повторное использование кода.

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

Но это еще не все! COM имеет другое правило это тривиально легко понять, но часто упускают из виду:

С точки зрения COM-клиента подсчет ссылок всегда выполняется для каждого интерфейса. Клиенты никогда не должны предполагать, что объект использует один и тот же счетчик для всех интерфейсов.

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

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

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


Хорошо, но DirectX на самом деле не использует COM!

Истинный. DirectX использует небольшое подмножество COM, часто называемое Nano-COM< /а>. В то время как большая часть COM не применяется, аспекты ABI COM применимы. Поскольку в этом ответе говорится только об аспектах ABI, он применим как к COM, так и к DirectX.

См. Документы Microsoft.

person IInspectable    schedule 01.07.2021
comment
в этом случае не нужно никаких корректировок указателя - person RbMm; 01.07.2021
comment
@rbm На основании какого правила? Я не спрашиваю, можете ли вы найти реализацию, в которой это не ломается. Я прошу спецификацию, которая утверждает, что это всегда будет работать. - person IInspectable; 01.07.2021
comment
На основе понимания. если объект реализует 2 интерфейса - I1 и I2, которые не наследуются один от другого - всегда будут разные vtables и настройка указателя. если I2 : I1 - мы можем использовать общую виртуальную таблицу - никогда не нужна настройка указателя - person RbMm; 01.07.2021
comment
@rbm Верно, мы можем использовать общую виртуальную таблицу. Теперь COM не требует повторного использования виртуальной таблицы для реализации наследования интерфейса. Единственное строгое требование, предъявляемое СОМ, заключается в том, что объект, наследующий интерфейс, должен реализовывать API этого интерфейса. И это все предположения, которые мы можем смело сделать. - person IInspectable; 01.07.2021
comment
здесь не нужно никаких предположений - любой метод I1 может быть вызван через указатель I2, если I2 наследуется от I1. и объект, который реализует I1, I2, должен реализовать это поведение. даже если существует 2 или более vtables до I1 внутри объекта. если вы этого не понимаете - это только ваши проблемы - person RbMm; 01.07.2021
comment
@RbMm Кажется, вы путаете API и ABI. I2 будет поддерживать I1 API, но может быть несовместим с ABI (отсюда и вопрос). Если это так, то приведение типов не будет работать. Теперь возможно, что текущая цепочка инструментов MSVC реализует его в совместимом с ABI виде, но вопрос был о COM в целом, а не об одной конкретной его реализации. - person marked-off-topic; 01.07.2021
comment
@marked-off-topic - нет, я не запутался, и мой ответ правильный. этот конкретный ответ неверен. попробуйте спросить себя - можете ли вы вызывать любые методы ID3D12GraphicsCommandListс указателем gcl? - person RbMm; 01.07.2021
comment
@marked-off-topic I2 конечно, полностью совместимый с I1. это не детали реализации - person RbMm; 01.07.2021
comment
@marked-off-topic - у вас есть ID3D12GraphicsCommandList* gcl - вы можете позвонить, например, gcl->GetType? с точно gcl как есть? - person RbMm; 01.07.2021
comment
@RbMm это C-часть SO. Не С++. И не Директ 3D. - person Chef Gladiator; 01.07.2021
comment
@ChefGladiator - и как здесь связан язык c? com интерфейс вообще рассчитан на использование с разных языков. я также могу задать вам ключевой вопрос - можно ли вызывать какие-либо методы ID3D12GraphicsCommandList с указателем на этот интерфейс - да или нет? - person RbMm; 01.07.2021
comment
@rbm Задает неправильный вопрос. Ответ на этот вопрос прост: да, конечно! Вопрос, который вы должны задать: гарантировано ли безопасное приведение от указателя интерфейса к указателю интерфейса, который он наследует? Ответ на этот вопрос также довольно прост: черт возьми, нет, это далеко не гарантировано. И да, OP прав, вы путаете API для ABI (или одну конкретную реализацию ABI для ABI). ABI не делает ни одно из обещаний, которые вы оцениваете, должны были быть правдой. - person IInspectable; 01.07.2021
comment
@IInspectable - Гарантируется ли безопасное приведение от указателя интерфейса к указателю интерфейса, который он наследует? - да, 100%. это гарантировано смыслом, который вы не можете или не хотите понять. если мы можем вызывать любые методы I2 с указателем p и базовым классом I1 для I2 - мы можем вызывать любые методы I1 с p тоже - потому что это и метод I2 также, которые мы можем - person RbMm; 01.07.2021
comment
вы выглядите как перепутанное приведение I2 из I1, которое может потребовать изменения двоичного значения указателя. а не через static_cast бит только QueryInterface. но преобразование I1 из I2 всегда нормально, и для этого не нужно использовать вызов QI. QI может даже вернуть другой двоичный указатель - в этом случае - оба указателя будут в порядке и могут быть использованы. как минимум 1 из них будет переходником регулятора. может быть и то и другое. но это уже детали реализации. - person RbMm; 01.07.2021
comment
@rbm Покажите мне конкретное правило COM, которое делает это утверждение правильным. Вы, кажется, изо всех сил пытаетесь найти его. Примите это как подсказку. - person IInspectable; 01.07.2021
comment
ты можешь, например, поесть? или вам нужны какие-то правила и инструкции для этого? я еще раз описываю вам смысл - если у нас есть указатель на I2* p и I2 : I1 (надеюсь, вы понимаете эту нотацию) - мы можем вызывать любые методы I1 с указателями excatly p как есть. просто потому, что это тоже I2 методы. все, что я могу вам посоветовать - спросите, например, Рэймонда Чена. может быть, он может лучше объяснить это для вас. почему мы можем преобразовать I2 в I1, но не можем преобразовать I1 в I2 без вызова QueryInterface. - person RbMm; 01.07.2021
comment
@rbm I2 : I1 (надеюсь, вы понимаете эту нотацию) - О да, я понимаю, что вы пытались выразить. Это вы не понимаете, что это значит. Поясню: Наследование в COM не не означает повторное использование кода. Дайте ему время переварить эту информацию. Это может показаться тривиальным, но все гораздо тоньше, чем вы ожидаете. Если вы дадите ему достаточно времени, чтобы переварить. - person IInspectable; 01.07.2021
comment
действительный указатель на I2 будет также действительным указателем на I1 (если I2 : I1) по прямому описанию. здесь не нужны никакие правила. QI от I2 до I1 может даже вернуть вам другое двоичное значение для указателя. в этом случае оба указателя будут правильными и могут использоваться (несмотря на разные двоичные значения). потому что в этом случае будут разные vtables и функции - внутри объекта функции, который реализует интерфейс, уже настраивается значение указателя, обычно на указатель объекта this - person RbMm; 01.07.2021
comment
Просто потрясающе, конечно, непонятна элементарная вещь - если мы можем вызвать любой метод из I2 с указателем p - мы можем вызвать любой метод из I1 с таким же указателем p - просто потому, что любой метод из I1 - будет методом I2.. - person RbMm; 01.07.2021
comment
@IInspectable - похоже, у вас очень слабые знания в этой теме. да - QI может вернуть другое двоичное значение для I1. но в этом случае оба указателя будут в порядке. Почему ? потому что это укажет на разные таблицы функций. и будут разные указатели в этой таблице. вы слышали о преобразователе настройки? Может быть, вы попробуете задать этот вопрос Рэймонду Чену? и я никогда не говорю, что QI просто переинтерпретирует приведение. я настаиваю - могут быть разные двоичные указатели после QI преобразования I2 в I1 - но оба в порядке - person RbMm; 01.07.2021
comment
@IInspectable и мой ответ о сравнении guid также верны - количество голосов за или против - не доказательство - person RbMm; 01.07.2021
comment
если I2* p и I2 : I1 мы можем вызывать любые I1 методы с указателем p. в результате p действительный указатель на интерфейс I1. достаточно. для большего понимания - даже если могут быть другие I1* q и q != p (на двоичном уровне) - в этом случае это просто указатель на другую виртуальную таблицу с другими функциями. в одной (или обеих) таблице будут указатели на переходники регулятора. и оба p и q будут правильными. и заметьте - я не говорю, что обратное приведение (I1 -> I2) правильно. обратное неверно - person RbMm; 01.07.2021
comment
Наследование в COM не означает повторное использование кода. и как это связано с приведением (назначением) указателя IDerived* p; к IBase* q = p; ? использование после этого q (q->method(..)) будет иметь точно такой же двоичный (ABI) эффект, что и вызов p->method(..). это эквивалентно вызову методов IBase по указателю IDerived, что, конечно, абсолютно нормально и законно. - person RbMm; 03.07.2021
comment
Это не нормально и не законно. Я подробно объяснил это в своем ответе. Наследование в COM означает повторное использование интерфейса. Повторное использование интерфейса не означает повторное использование поведения. Для IBase::method() совершенно законно вести себя иначе, чем IDerived::method(). Таким образом, если вы приведете IDerived* p к IBase* и вызовете p->method(), вы получите поведение IDerived, но вы хотели поведение IBase. - person IInspectable; 03.07.2021

Будет ли работать QueryInterface?

Да.

Нужно ли мне делать что-то еще?

No.

Код у вас в порядке. Вы также можете сделать так:

ID3D12GraphicsCommandList *gcl = ...;
ID3D12CommandList *cl;
HRESULT result = gcl->lpVtbl->QueryInterface(gcl,
                                             &IID_ID3D12CommandList,
                                             (void**)&cl);
person fpiette    schedule 01.07.2021
comment
Это в точности то, что уже делает OP (за исключением того, что они используют макросы, доступные при определении COBJMACROS). Плюс, как всегда, ответ, который не дает обоснования, на самом деле бесполезен. - person IInspectable; 01.07.2021
comment
Макрос IID_PPV_ARGS() будет безопаснее. , если доступно: HRESULT result = gcl->lpVtbl->QueryInterface(gcl, IID_PPV_ARGS(&cl)); - person Remy Lebeau; 01.07.2021

в случае, если c++ у вас уже есть указатель на ID3D12CommandList, потому что ID3D12GraphicsCommandList унаследовано от ID3D12CommandList. в случае c вам нужно формальное приведение (ID3D12CommandList*)gcl для использования этого в качестве указателя ID3D12CommandList*. использовать QueryInterface в конкретном случае не нужно - конечно можно использовать, но делать это нет смысла. снова - указатель на ID3D12GraphicsCommandList - уже действительный указатель на ID3D12CommandList тоже. потому что указатель на ID3D12GraphicsCommandList - это указатель на указатель на таблицу функции (ID3D12GraphicsCommandListVtbl), которая совместима по макету (содержащая в начале) с ID3D12CommandListVtbl. поэтому любой метод ID3D12CommandList может быть вызван через указатель ID3D12GraphicsCommandList как есть


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

в частности - если у нас есть указатель (gcl) на интерфейс ID3D12GraphicsCommandList, мы можем вызвать любой метод ID3D12GraphicsCommandList с этим (gcl) указателем.

в результате мы можем вызвать любой метод ID3D12CommandList с точно двоичным значением gcl как есть, потому что метод ID3D12CommandList также является методом ID3D12GraphicsCommandList.

в общем, если какой-то объект реализует 2 интерфейса I2 и I1, а I2 наследуется от I1 ( I2 : I1 в терминах c++), мы всегда можем преобразовать указатель I2* в указатель I1*.

Делать это в обратном направлении неправильно — если у нас есть указатель на I1*, мы не можем привести его к I2*. это уже требует использования QueryInterface. например - пусть существует I3 : I1 и объект реализует все 3 интерфейса - I1, I2 и I3. и I2, и I3 наследуются от I1, но I2 и I3 не наследуются друг от друга, имеют разную компоновку. в этом случае I2 и I3 всегда будут иметь разные указатели. 2 разные виртуальные таблицы. и I1* может указывать на I3* vtable вместо I2* vtable.

so

I2* p2;
I1* p1 = (I1*)p2;// cast need only for c, not need for c++

всегда в порядке. но следующий код неверен

I1* p1;
I2* p2 = (I2*)p1;// wrong !!

но вопрос был о I2 -> I1 приведении, а не о I1 -> I2 приведении

person RbMm    schedule 01.07.2021
comment
@IInspectable здесь вообще никаких предположений. мы можем вызывать любые методы ID3D12CommandList, используя указатель на ID3D12GraphicsCommandList как есть. потому что ID3D12GraphicsCommandList содержит все эти методы - person RbMm; 01.07.2021
comment
Конечно, ID3D12GraphicsCommandList реализует все функции, которые реализует ID3D12CommandList. В конце концов, это определение COM для наследования интерфейсов. Вывод из этого, что было безопасно просто переинтерпретировать указатель интерфейса как другой указатель интерфейса, является предположением. Если вы не предоставите правила в спецификации COM, которые гарантируют это предположение, это предположение является необоснованным и безосновательным. - person IInspectable; 01.07.2021
comment
Вы делаете разные заявления. 1 ID3D12GraphicsCommandList наследует интерфейс ID3D12CommandList. Это несомненно правильно. 2 Таким образом, безопасно превратить ID3D12GraphicsCommandList* в ID3D12CommandList*. Это неправильно, но ваш ответ настаивает на том, что это гарантированно безопасно. Опять же, либо предоставьте ссылку на спецификацию COM, гарантирующую безопасность, либо оцените вероятность того, что вы действительно ошибаетесь. - person IInspectable; 01.07.2021
comment
@IInspectable - если у нас есть ID3D12GraphicsCommandList *gcl - мы можем вызывать любые методы ID3D12GraphicsCommandList с помощью этого указателя. как результат и любые методы ID3D12CommandList с именно этим указателем - потому что любые методы ID3D12CommandList - тоже метод ID3D12GraphicsCommandList и мы можем вызвать его с помощью gcl. если I2 : I1 мы всегда можем преобразовать I2 в I1. в другом направлении - привести I1 к I2 - это уже может быть неправильно (всегда неправильно по дизайну), потому что указатель на I1 vtable может не быть указателем на I2 vtable. тут уже нужно QI - person RbMm; 01.07.2021
comment
если I2 : I1 мы всегда можем преобразовать I2 в I1. Укажите мне конкретное правило COM, которое делает это предположение фактом, и мы поговорим. До тех пор это не более чем оптимистичная экстраполяция конкретной детали реализации в общее правило, у которого не будет шанса выжить в аду. - person IInspectable; 01.07.2021
comment
@RbMm это C-часть SO. Не С++. И не Директ 3D. - person Chef Gladiator; 01.07.2021
comment
@ChefGladiator - и? какой конкретно неверный с твоего взгляда? - person RbMm; 01.07.2021
comment
Пожалуйста, используйте только C, а в случае COM использование IDL значительно проясняет ситуацию. - person Chef Gladiator; 01.07.2021
comment
@ChefGladiator - я думаю, что это основной вопрос com. com основан на каком-то бинарном коде, макете и т. д. Он не привязан к конкретному языку. уже задача языка найти описания соответствующие сущности. я описываю суть в том, что мы можем вызывать любые методы ID3D12GraphicsCommandList с указателем на этот интерфейс. в результате мы можем вызывать и любые методы ID3D12CommandList именно с этим указателем (без бинарной модификации указателя) так что QueryInterface здесь не нужен. его можно использовать, но не нужно. что здесь не так? - person RbMm; 01.07.2021
comment
Это не суть COM. Суть реализации COM заключается в IDL, который компилируется в код C. Никакого C++ и уж точно никакого Direct 3D. ID3D... API здесь запутывает проблему. И предлагаемое решение. - person Chef Gladiator; 01.07.2021
comment
@che IDL не компилируется в код C. Это независимое от языка описание интерфейса, которое инструменты могут преобразовывать в заголовочные файлы C или C++ или вообще во что-то еще. И уж точно IDL не связан с реализацией COM-объекта. Вообще. Он описывает интерфейс. И это все. Для меня загадка, почему вы считаете, что просмотр IDL был хоть каким-то просветлением. Этот вопрос касается гарантий COM, поскольку они относятся конкретно к DirectX. - person IInspectable; 01.07.2021
comment
@IInspectable предоставить ссылку на спецификацию COM? Не существует документа спецификации COM, все, что делает MSVC, всегда было «спецификацией». - person M.M; 02.07.2021
comment
Правила COM @m.m прописаны вне. Я ищу конкретное правило, которое требует, чтобы наследование интерфейса требовало повторного использования кода в реализации. - person IInspectable; 02.07.2021
comment
@IInspectable - и что конкретно вы пытаетесь сказать? просто вставлять ссылки нет смысла - person RbMm; 02.07.2021
comment
@IInspectable - и вы можете понизить голосование или опубликовать ответ самостоятельно, или пометить как дубликат также здесь - it-inherits" title="приведение интерфейса com к интерфейсу, от которого он наследуется"> stackoverflow.com/questions/68217819/ - person RbMm; 02.07.2021
comment
@ChefGladiator - насколько среднее, простое отношение к теме. я основываюсь на очень простом факте - указатель на интерфейс I2 уже действителен, и бинарный такой жеуказатель на интерфейс I1 тоже, если I2 наследуется от I1 и от что такое внутренний интерфейс. - person RbMm; 02.07.2021
comment
@RbMm, как я прокомментировал ваш двойной вопрос, который выглядит как ответ: пожалуйста, опубликуйте репозиторий Github, где это работает. Затем, пожалуйста, запросите проверку кода в части проверки кода SO. - person Chef Gladiator; 02.07.2021
comment
@ChefGladiator - какая работа?? это приведение, конечно, работает в любом примере. вы можете попробовать это самостоятельно. но вы можете создать пример, где это неправильно?! - person RbMm; 02.07.2021