динамический бросок с интерфейсами

  • Найдите изображение с помощью docker ps -a
  • Затем проверьте изображение docker image history --no-trunc image_name
7
задан Evan Teran 25 May 2011 в 14:53
поделиться

5 ответов

Я наконец понял это, Daniel Paull был корректен в этом "боком dybnamic_cast"должен быть позволен. Моя проблема состояла в том, потому что мой код вовлекает совместно использованные библиотеки. typeinfo от PluginA не был доступен в PluginB. Мое решение состояло в том, чтобы эффективно добавить RTLD_NOW и RTLD_GLOBAL к моему процессу загрузки

технически это было

loader.setLoadHints(QLibrary::ResolveAllSymbolsHint | QLibrary::ExportExternalSymbolsHint);

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

3
ответ дан 6 December 2019 в 10:03
поделиться

Каждый класс имеет по крайней мере один виртуальный метод? В противном случае существует Ваша проблема. Добавление виртуального деструктора к каждому классу должно преодолеть проблему.

Следующее счастливо работало на меня:

class IC
{
public:
    virtual ~IC() {}
};

class IB
{
public:
    virtual ~IB() {}
};

class A
{
public:
    virtual ~A() {}
    void foo() { /* stick a breakpoint here to confirm that this is called */ }
};

class T : public A, public IB, public IC 
{
public:
    virtual ~T() {}
};


int main(void)
{
    IB *b_ptr = new T;
    A *a_ptr = dynamic_cast<A *>(b_ptr);
    a_ptr->foo();
    return 0;
}

Править:

После всей новой информации и необычного поведения (Ваш код должен просто работать!), следующее помогает? Я представил интерфейс под названием IObject и использую виртуальное наследование, чтобы гарантировать, что существует только одна копия этого базового класса. Можно ли теперь бросить к IObject и затем к A?

class IObject
{
public:
    virtual ~IObject() {}
};

class IC : virtual public IObject
{
public:
    virtual ~IC() {}
};

class IB : virtual public IObject
{
public:
    virtual ~IB() {}
};

class A : virtual public IObject
{
public:
    virtual ~A() {}
    void foo() { /* stick a breakpoint here to confirm that this is called */ }
};

class T : virtual public A, virtual public IB, virtual public IC
{
public:
    virtual ~T() {}
};


int main()
{
    IB *b_ptr = new T;
    A *a_ptr = dynamic_cast<A *>( dynamic_cast<IObject *>(b_ptr) );
    a_ptr->foo();
    return 0;
}

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

7
ответ дан 6 December 2019 в 10:03
поделиться

Существует ли надлежащий способ сделать это? Или я должен реализовать работу вокруг? Я думал о наличии и IB и IC, наследовались фактически A, но в прошлый раз IIRC я попробовал это были некоторые сложности, которые сделали это нежелательным.

Я беру его затем, что определения IB и IC находятся под Вашим контролем.

Существует путь, которым COM-интерфейсы работают над Windows; они делают то, что Вы желаете, хотят сделать, т.е.:

  • Бросок от одного интерфейса до другого
  • Реализация непрозрачна вызывающей стороне
  • Только реализация знает, какие интерфейсы она реализует

Действительно сделайте это, можно сделать что-то как (непротестированный код вперед)...

interface IQueryInterface
{
  IQueryInterface* queryInterface(const Guid* interfaceId);
};

interface IB : public abstract IQueryInterface
{
  ...
};

interface IC : public abstract IQueryInterface
{
  ...
};

//within your implementation class
IQueryInterface* T::queryInterface(const Guid* interfaceId)
{
  if (matches(interfaceId,GUID_IB))
    return (IB*)this;
  if (matches(interfaceId,GUID_IC))
    return (IC*)this;
  if (matches(interfaceId,GUID_A))
    return (A*)this;
  return 0;
}

Намного более простая, более трудно кодированная версия этого была бы:

class A; //forward reference
interface IB
{
  virtual A* castToA() { return 0; }
};
class T : public A, IB, IC
{
  virtual A* castToA() { return this; }
};
5
ответ дан 6 December 2019 в 10:03
поделиться

Бросок к T* сначала затем к A:

IB *b_ptr = new T; // it's really more complicated, but serves the example
A *a_ptr = dynamic_cast<T *>(b_ptr);

Если IB в целом должен быть castable к A, то, возможно, IB должен наследоваться A.

Править: Я просто попробовал это, и это работает - отмечают, что E неизвестен во время компиляции основного метода.

struct A
{
    virtual ~A() {}
};

struct C
{
    virtual ~C() {}
};

A* GetA();

int main()
{
    C *y = dynamic_cast<C *>(GetA());
    if (y == NULL)
        cout << "Fail!";
    else
        cout << "Ok!";
}

struct E : public A, public C
{
}; 

A* GetA() { return new E(); }
3
ответ дан 6 December 2019 в 10:03
поделиться

Меня также недавно беспокоила такая же проблема. Для получения дополнительной информации см. Раздел часто задаваемых вопросов GCC:

http://gcc.gnu.org/faq.html#dso

Помимо указания dlopen с помощью флагов RTLD_ *, некоторые варианты этой проблемы могут быть решены компоновщиком как Что ж, посмотрите его символы -E и -B.

1
ответ дан 6 December 2019 в 10:03
поделиться
Другие вопросы по тегам:

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