无法访问在标准回调中传递的对象变量
Can't access object variables passed in a std callback
我有一个回调函数(在我的 class 之外),我将 BassMusicPlayer class 对象作为参数传递。如果在其中打断点,我可以看到 'self'.
中的所有变量和方法
如果我尝试 read/print 这些值,它将无法编译并给出错误 C2027:使用未定义类型 'BassMusicPlayer'。我还按照其他人的建议将 static 添加到 class 定义中。我可以使用全局变量作为解决方法,但我真的想避免这样做。
这是我的 class 文件中的内容:
class BassMusicPlayer;
void __stdcall LoopSyncProc(HSYNC handle, DWORD channel, DWORD data, void *user) {
BassMusicPlayer * self = reinterpret_cast<BassMusicPlayer*>(user);
//printf("%d\n", self->loop_start);
//if (!BASS_ChannelSetPosition(channel, self->loop_start, BASS_POS_BYTE))
if (!BASS_ChannelSetPosition(channel, 0, BASS_POS_BYTE)) // try seeking to loop start
BASS_ChannelSetPosition(channel, 0, BASS_POS_BYTE); // failed, go to start of file instead
}
class BassMusicPlayer {
private:
std::string m_filename;
int m_filetype;
int m_music_handle;
BassMusicPlayer* m_music;
HWND m_handle;
DWORD m_sample_rate;
SYNCPROC* m_callback_proc;
public:
QWORD loop_start, loop_end;
// constructor
BassMusicPlayer(HWND handle, DWORD sample_rate, SYNCPROC* callback_proc) {
m_handle = handle;
m_sample_rate = sample_rate;
m_callback_proc = LoopSyncProc;
}
bool OpenMusicFile(std::string filename, QWORD seek_start, QWORD file_length, bool start_playing, bool loop, QWORD loopstart, QWORD loopend) {
loop_start = loopstart;
loop_end = loopend;
m_music_handle = BASS_MusicLoad(false, filename.c_str(), 0, 0, BASS_MUSIC_POSRESET, m_sample_rate);
BASS_ChannelSetSync(m_music_handle, BASS_SYNC_END | BASS_SYNC_MIXTIME, 0, m_callback_proc, this);
}
};
为什么我的 BassMusicPlayer class 只有在我想访问它的变量时才被识别?
问题是在编译该函数时,类型没有完全定义。简单的声明 (class BassMusicPlayer;
) 不是完整的定义。
解决方案是移动函数定义,使整个 class 定义已经在范围内。
在您定义 LoopSyncProc
的代码中,您只是声明了 BassMusicPlayer
。您已经告诉编译器:"there exists a class called BassMusicPlayer
",仅此而已。
您可以获取指向前向声明的 class 的指针,但您无法访问对象本身 - 此时编译器对对象的 class 一无所知,或者如何访问它。
您需要将 LoopSyncProc
移到 BassMusicPlayer
下面。为此,您需要转发声明 LoopSyncProc
:
void __stdcall LoopSyncProc(HSYNC handle, DWORD channel, DWORD data, void *user);
class BassMusicPlayer {
...
};
void __stdcall LoopSyncProc(HSYNC handle, DWORD channel, DWORD data, void *user) {
BassMusicPlayer * self = reinterpret_cast<BassMusicPlayer*>(user);
//printf("%d\n", self->loop_start);
//if (!BASS_ChannelSetPosition(channel, self->loop_start, BASS_POS_BYTE))
if (!BASS_ChannelSetPosition(channel, 0, BASS_POS_BYTE)) // try seeking to loop start
BASS_ChannelSetPosition(channel, 0, BASS_POS_BYTE); // failed, go to start of file instead
}
无法识别您的 BassMusicPlayer,因为您有这个:
class BassMusicPlayer;
这称为前向声明。它告诉编译器 class BassMusicPlayer
存在,但它没有告诉它 class 是什么,它的对象需要多少 space,或者它有什么成员.因为指针只是整数,在您尝试对它们做某事之前它们指向什么并不重要,编译器可以很好地使用指针,但是当您尝试取消引用其中一个指针时(例如通过访问它的函数或->
运算符的变量),编译器会失败,因为它不知道如何执行此操作。直到稍后实际声明 class,在 你的回调之后,它才发现。
要解决此问题,请将回调移动到 class 的声明之后。因为您必须知道 class 中的函数,所以您应该转发声明 函数 ,如下所示:
void __stdcall LoopSyncProc(HSYNC handle, DWORD channel, DWORD data, void *user);
您的代码的总体顺序应为:
- 转发声明LoopSyncProc函数
- 声明 class
- 定义 LoopSyncProc 函数
我有一个回调函数(在我的 class 之外),我将 BassMusicPlayer class 对象作为参数传递。如果在其中打断点,我可以看到 'self'.
中的所有变量和方法如果我尝试 read/print 这些值,它将无法编译并给出错误 C2027:使用未定义类型 'BassMusicPlayer'。我还按照其他人的建议将 static 添加到 class 定义中。我可以使用全局变量作为解决方法,但我真的想避免这样做。
这是我的 class 文件中的内容:
class BassMusicPlayer;
void __stdcall LoopSyncProc(HSYNC handle, DWORD channel, DWORD data, void *user) {
BassMusicPlayer * self = reinterpret_cast<BassMusicPlayer*>(user);
//printf("%d\n", self->loop_start);
//if (!BASS_ChannelSetPosition(channel, self->loop_start, BASS_POS_BYTE))
if (!BASS_ChannelSetPosition(channel, 0, BASS_POS_BYTE)) // try seeking to loop start
BASS_ChannelSetPosition(channel, 0, BASS_POS_BYTE); // failed, go to start of file instead
}
class BassMusicPlayer {
private:
std::string m_filename;
int m_filetype;
int m_music_handle;
BassMusicPlayer* m_music;
HWND m_handle;
DWORD m_sample_rate;
SYNCPROC* m_callback_proc;
public:
QWORD loop_start, loop_end;
// constructor
BassMusicPlayer(HWND handle, DWORD sample_rate, SYNCPROC* callback_proc) {
m_handle = handle;
m_sample_rate = sample_rate;
m_callback_proc = LoopSyncProc;
}
bool OpenMusicFile(std::string filename, QWORD seek_start, QWORD file_length, bool start_playing, bool loop, QWORD loopstart, QWORD loopend) {
loop_start = loopstart;
loop_end = loopend;
m_music_handle = BASS_MusicLoad(false, filename.c_str(), 0, 0, BASS_MUSIC_POSRESET, m_sample_rate);
BASS_ChannelSetSync(m_music_handle, BASS_SYNC_END | BASS_SYNC_MIXTIME, 0, m_callback_proc, this);
}
};
为什么我的 BassMusicPlayer class 只有在我想访问它的变量时才被识别?
问题是在编译该函数时,类型没有完全定义。简单的声明 (class BassMusicPlayer;
) 不是完整的定义。
解决方案是移动函数定义,使整个 class 定义已经在范围内。
在您定义 LoopSyncProc
的代码中,您只是声明了 BassMusicPlayer
。您已经告诉编译器:"there exists a class called BassMusicPlayer
",仅此而已。
您可以获取指向前向声明的 class 的指针,但您无法访问对象本身 - 此时编译器对对象的 class 一无所知,或者如何访问它。
您需要将 LoopSyncProc
移到 BassMusicPlayer
下面。为此,您需要转发声明 LoopSyncProc
:
void __stdcall LoopSyncProc(HSYNC handle, DWORD channel, DWORD data, void *user);
class BassMusicPlayer {
...
};
void __stdcall LoopSyncProc(HSYNC handle, DWORD channel, DWORD data, void *user) {
BassMusicPlayer * self = reinterpret_cast<BassMusicPlayer*>(user);
//printf("%d\n", self->loop_start);
//if (!BASS_ChannelSetPosition(channel, self->loop_start, BASS_POS_BYTE))
if (!BASS_ChannelSetPosition(channel, 0, BASS_POS_BYTE)) // try seeking to loop start
BASS_ChannelSetPosition(channel, 0, BASS_POS_BYTE); // failed, go to start of file instead
}
无法识别您的 BassMusicPlayer,因为您有这个:
class BassMusicPlayer;
这称为前向声明。它告诉编译器 class BassMusicPlayer
存在,但它没有告诉它 class 是什么,它的对象需要多少 space,或者它有什么成员.因为指针只是整数,在您尝试对它们做某事之前它们指向什么并不重要,编译器可以很好地使用指针,但是当您尝试取消引用其中一个指针时(例如通过访问它的函数或->
运算符的变量),编译器会失败,因为它不知道如何执行此操作。直到稍后实际声明 class,在 你的回调之后,它才发现。
要解决此问题,请将回调移动到 class 的声明之后。因为您必须知道 class 中的函数,所以您应该转发声明 函数 ,如下所示:
void __stdcall LoopSyncProc(HSYNC handle, DWORD channel, DWORD data, void *user);
您的代码的总体顺序应为:
- 转发声明LoopSyncProc函数
- 声明 class
- 定义 LoopSyncProc 函数