Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/126.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ c++;调用指针时typedef访问冲突_C++ - Fatal编程技术网

C++ c++;调用指针时typedef访问冲突

C++ c++;调用指针时typedef访问冲突,c++,C++,我有以下代码: (exe) (.cpp) 我复制了这个系统,应该是这样的,因为我不能在一边修改代码。 为什么我会被侵犯访问权限?调用“val(obj,ref)”我希望是指向类的指针+指向方法调用的偏移量。指向成员的指针不是“指向类的偏移量”。没有这样的东西。在某些情况下(例如指向具有简单继承层次结构的类中的虚拟成员函数的指针),其实现可以由这样的偏移量(加上可能的一些其他数据位)组成 然而,对于非虚拟函数(如您的示例中),它下面可能有一个指向函数的普通指针。非虚拟函数不存储在任何带有“偏移量”的

我有以下代码: (exe)

(.cpp)

我复制了这个系统,应该是这样的,因为我不能在一边修改代码。
为什么我会被侵犯访问权限?调用“val(obj,ref)”我希望是指向类的指针+指向方法调用的偏移量。

指向成员的指针不是“指向类的偏移量”。没有这样的东西。在某些情况下(例如指向具有简单继承层次结构的类中的虚拟成员函数的指针),其实现可以由这样的偏移量(加上可能的一些其他数据位)组成

然而,对于非虚拟函数(如您的示例中),它下面可能有一个指向函数的普通指针。非虚拟函数不存储在任何带有“偏移量”的“表”中(至少没有理由这样存储它们),它们很可能被实现为普通的bog标准函数,具有一个损坏的名称和一个预先指定的参数

指向成员的指针是C++中一个比较棘手的部分,主要是因为没有明显的映射到实现概念,不同的编译器可以以不同的方式处理它们。相信

void(Dummy::*)(int)
void(Test::*)(int)
是二进制兼容的是非常脆弱的

通常,您不能期望指向
Dummy::callMe
的指针的二进制表示形式与指向
Test
的成员函数的指针的二进制表示形式有任何相似之处,因为它可能过于依赖
Dummy
Test
的定义,以及编译器如何实现指向成员的指针

最重要的是,visualstudio的编译器在默认情况下处理指向成员的指针的方式是不一致的(因此,从大多数角度来看,是不一致的)。这种默认处理方式是这样的,为了正确地形成指向类成员的指针,编译器需要看到类的定义。原因是指向成员的指针的最通用实现相当大(我相信是4个本地单词),因为它必须考虑虚拟继承等。最常见的情况是,单个基类没有虚拟对象,可以放在本地单词中

因此,如果您希望使用完全标准的C++结构,比如接受指向其定义在站点不可见的类的成员的指针,则必须使用编译标志。因此,将始终使用最通用的表示法

默认行为
/vmb
,根据
A
的定义优化
A::*
的二进制表示(包括大小!)。因此,在这种行为有效的情况下,不可能创建像您这样的typedef


至于你的选择是什么:

  • 如果必须通过C风格接口,则在调用回调的一侧强制使用C风格函数作为回调,并在注册的一侧创建包装器C风格函数。大概是这样的:

    class Dummy
    {
      void callMe(int) {}
    };
    
    extern "C" void fw_Dummy_callMe(void *self, int i)
    { static_cast<Dummy*>(self)->callMe(i); }
    
  • >P>如果您可以在接口中有C++(即编译器和版本在DLL接口的两侧总是相同),那么可以使用指向成员函数的指针:
  • 双方不会看到该类的不同定义。不过,如果其中一个只有一个非定义声明,那也没关系。为100% C++的一致性,类的名称应该相同。
  • 在构建DLL及其客户端时使用
    /vmg

可能
LoadLibraryA
返回空值或
GetProcAddress
返回空值?您使用的是Visual Studio吗?是的,我在Visual Studio上,没有LoadLibraryA加载正确。使用debug,我可以访问“(Object->*reference)(1);”,但调用会导致崩溃。实际上,看起来您正在将指向Init函数的指针强制转换为不兼容类型的potiner。因为dll和exe中的
Referece
的签名不同。指向不同
Dummy
Test
类的非静态成员函数(即使具有相同的签名)的指针不兼容。一般来说,C++函数的指针不应该通过C风格的接口。C++不只是调用“对象指针+ OffStC类”调用?我想说的是:相信我,调用它。我怎样才能创建一个指向so方法的好指针?我需要注册一个回调。如果你要使用C风格的接口,那么就使用C风格的类型:一个指向类实例的void指针和一个指向常规函数的指针。我接受你的回答,因为我解决了我的POC代码问题,但实际上(我正在使用虚幻引擎并为它创建外部dll)不能用标志构建。
#pragma once  

#define DLL_EXPORT __declspec(dllexport)

class Test;
typedef void (Test::*Reference)(int a);

#ifdef __cplusplus
extern "C"
{
#endif
    void DLL_EXPORT Init(Test* Object, Reference reference);

#ifdef __cplusplus
}
#endif
#include "your.h"

void DLL_EXPORT Init(Test * Object, Reference reference)
{
    (Object->*reference)(1);
}
class Dummy
{
  void callMe(int) {}
};

extern "C" void fw_Dummy_callMe(void *self, int i)
{ static_cast<Dummy*>(self)->callMe(i); }
#ifdef __cplusplus
extern "C"
{
#endif
    void DLL_EXPORT Init(void* Object, void (*reference)(void*, int));

#ifdef __cplusplus
}
#endif