docker ps -a
docker image history --no-trunc image_name
Я наконец понял это, Daniel Paull был корректен в этом "боком dybnamic_cast
"должен быть позволен. Моя проблема состояла в том, потому что мой код вовлекает совместно использованные библиотеки. typeinfo от PluginA не был доступен в PluginB. Мое решение состояло в том, чтобы эффективно добавить RTLD_NOW
и RTLD_GLOBAL
к моему процессу загрузки
технически это было
loader.setLoadHints(QLibrary::ResolveAllSymbolsHint | QLibrary::ExportExternalSymbolsHint);
потому что я использую сменную систему QT, но то же различие. Эти флаги вынуждают все символы загруженные библиотеки быть сразу разрешенными и видимы к другим библиотекам. Поэтому делая typeinfo для всех, которым был нужен он. dynamic_cast
работавший как ожидалось, после того как эти флаги существовали.
Каждый класс имеет по крайней мере один виртуальный метод? В противном случае существует Ваша проблема. Добавление виртуального деструктора к каждому классу должно преодолеть проблему.
Следующее счастливо работало на меня:
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;
}
Я не предполагаю, что это - правильное решение, но это могло бы предложить некоторую информацию относительно того, что продолжается...
Существует ли надлежащий способ сделать это? Или я должен реализовать работу вокруг? Я думал о наличии и 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; }
};
Бросок к 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(); }
Меня также недавно беспокоила такая же проблема. Для получения дополнительной информации см. Раздел часто задаваемых вопросов GCC:
http://gcc.gnu.org/faq.html#dso
Помимо указания dlopen с помощью флагов RTLD_ *, некоторые варианты этой проблемы могут быть решены компоновщиком как Что ж, посмотрите его символы -E и -B.