Учитывая базовый класс B
, такие как:C++: Нарушение прав доступа при заливке пустот * на указатель базового класса
class B
{
public:
virtual ~B() = default;
public:
virtual int f() const = 0;
};
и ряд производных классов Ai: public B
(I = 1, .., N), внедрение f()
, я получаю void*
, который определенно содержит один из полученных классов Ai
из внешней программы - для выполнения метода f()
.
Можно создать точку входа для каждого возможного производного типа, и он будет работать нормально:
// for each derived class Ai
void executeF(void* aPtr, int* result)
{
auto aObjPtr = static_cast<Ai*>(aPtr);
*result = aObjPtr->f();
}
Однако, это должно быть возможно достигнуть того же результата с только одной функции, такие как:
void executeF(void* aPtr, int* result)
{
auto bObjPtr = static_cast<B*>(aPtr); // works
*result = bObjPtr->f(); // Access violation
}
случай удается выше, но исполнение f()
терпит неудачу с «нарушение прав доступа» в MSVC 2013.
есть S что-то не так с вышеуказанной функцией? И если это так, есть ли способ решить задачу с помощью одной функции?
Я прочитал некоторые материалы, в которых утверждается, что нужно наложить void*
только на тот класс, который он держит (также предлагается в комментарии ниже). Тем не менее, этот код компилирует и выполняет отлично: http://ideone.com/e0Lr6v
Некоторые больше контекста о том, как все называют:
я не могу предоставить весь код здесь, потому что это слишком долго, но в целом .. Функция executeF
, конструкторы для объектов Ai
и все в библиотеке, которая определяет и работает на объектах A
, B
предоставляются в качестве экспортируемых функций, которые работают только с типами void*
. Просто FYI, эта библиотека скомпилирована и построена с помощью MSVC 2013.
Другая сторона (оболочка для языка R) скомпилирована и построена с помощью g ++ - она динамически загружает указанную библиотеку, экспортирует необходимую функцию и вызывает ее. Единственное, что доступно на этой стороне, это объекты void*
, содержащие объекты Ai
- он просто отправляет запросы на создание объектов, называет их методы, освобождает их.
Например (схематично), создать объект типа A1:
// "objects" library
void createA1(void** aObj)
{
*a1Obj = new A1();
}
// caller library
auto const createA1func = (int(__CC *)(void**)) GetProcAddress(getDLL(), "CreateA1");
void* a1Obj = NULL;
createAFunc(a1Obj);
// ... return the a1Obj to the external environemnt to keep it around
Затем, a1Obj
вокруг, сделать какую-то работу с ним:
// caller library
auto const executeFfunc = (int(__CC *)(void*, int*)) GetProcAddress(getDLL(), "executeF");
int res(0);
executeFfunc(a1Obj, &res);
Так что, если я пишу отдельную функцию для каждого типа Ai
на с обеих сторон, все работает нормально. Но это было бы значительно меньше кода шаблона, если бы я мог каким-то образом использовать базовый класс.
Вы можете попробовать выполнить кастинг перед вызовом 'executeF', так что' executeF' всегда получает 'B *' вместо 'Ai *' – immibis
Почему это помечено C? – immibis
Внешняя программа @immibis, которая передает 'void *', не знает о типах 'B',' A' и т. Д. –