给出两个类:X
和Y
。 X
包含Y *
类型的成员,并将指向其成员函数的指针传递给Y
的实例。所以在C ++中它看起来像这样:
x.h
#pragma once
class Y;
class X
{
public:
X();
private:
Y *y;
void myfunc(int);
};
x.cpp
#include "x.h"
#include "y.h"
X::X()
{
this->y = new Y(*this, &X::myfunc);
}
void X::myfunc(int dummy)
{
dummy = dummy;
}
y.h
#pragma once
//#include "x.h" // this would fix the issue!
class X;
class Y
{
public:
Y(X &x, void (X::*pMyCallback)(int));
~Y();
private:
X &x;
void (X::*pMyCallback)(int) = nullptr;
};
y.cpp的
#include "y.h"
#include "x.h"
Y::Y(X &x, void (X::*pMyCallback)(int))
: x(x), pMyCallback(pMyCallback)
{
(x.*pMyCallback)(3);
}
Y::~Y()
{
}
当我运行此代码时,Visual Studio 2015引发了异常:" MYPROGRAM.exe触发了断点"。有时它会因访问冲突异常而崩溃。
int main(int argc, char *argv[])
{
X x;
return 0;
}
我注意到这个问题与编译单元有某种关系,因为如果我在同一个文件中定义X
和Y
,它就不会崩溃。此外,如果我将X
(即" x.h")的声明包含在" y.h"中,它也不会崩溃。
这种行为是否存在理由?
答案 0 :(得分:1)
问题似乎是,在声明类之后定义指向成员的指针,但在定义之前,MSVC必须猜测类#39;继承模型。有四种方法可以解决这个问题:
在" y.h"中的声明__single_inheritance
中使用特定于MS的关键字__multiple_inheritance
,__virtual_inheritance
或class X;
,强迫它使用特定的模型。其中,__single_inheritance
是最有效的,但只有在类没有多个或虚拟继承时才可用;由于X
没有基类,这很好。
// y.h
#pragma once
//#include "x.h" // this would fix the issue!
class __single_inheritance X;
class Y
{
public:
Y(X &x, void (X::*pMyCallback)(int));
~Y();
private:
X &x;
void (X::*pMyCallback)(int) = nullptr;
};
出于同样的原因,请使用特定于MS的编译指示pointers_to_members
。同样,我们可以使用"单继承",这是最有效的选择。
// y.h
#pragma once
#pragma pointers_to_members(full_generality, single_inheritance)
//#include "x.h" // this would fix the issue!
class X;
class Y
{
public:
Y(X &x, void (X::*pMyCallback)(int));
~Y();
private:
X &x;
void (X::*pMyCallback)(int) = nullptr;
};
更改IDE中的指针到成员的表示选项;不幸的是,我不确定如何做到这一点,因为我无法找到这个选项。
/vmg