无法访问在 std 回调中传递的对象变量



我有一个回调函数(ouside我的类),我将传递一个BassMusicPlayer类对象作为参数。如果在里面做一个断点,我可以看到self中的所有变量和方法。

如果我尝试读取/打印这些值,它将不会编译,并将给出错误C2027:使用未定义的类型">BassMusicPlayer"。我还按照其他人的建议在类定义中添加了static。我可以使用全局变量作为一种变通方法,但我真的想避免这样做。

这是我在课堂文件中的内容:

class BassMusicPlayer;
void __stdcall LoopSyncProc(HSYNC handle, DWORD channel, DWORD data, void *user) {
BassMusicPlayer * self = reinterpret_cast<BassMusicPlayer*>(user);
//printf("%dn", 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类的变量时,它才会被识别?

您的BassMusicPlayer无法识别,因为您有以下内容:

class BassMusicPlayer;

这被称为正向声明。它告诉编译器类BassMusicPlayer存在,但它不告诉它该类是什么,它的对象需要多少空间,或者它有什么成员。因为指针只是整数,在你尝试使用它们之前,它们指向什么并不重要,编译器可以很好地使用指针,但当你试图取消引用其中一个指针时(例如用->运算符访问其函数或变量),编译器会失败,因为它不知道如何做到这一点。直到稍后真正声明该类,在回调之后,它才会发现。

要解决此问题,请将回调移动到类声明后的。因为您必须了解类中的函数,所以应该转发声明函数,如下所示:

void __stdcall LoopSyncProc(HSYNC handle, DWORD channel, DWORD data, void *user);

代码的总体顺序应该是:

  • 转发声明LoopSyncProc函数
  • 声明类
  • 定义LoopSyncProc函数

在定义LoopSyncProc的代码中,您只声明了BassMusicPlayer。您已经告诉编译器:"存在一个名为BassMusicPlayer的类",仅此而已。

您可以将指针指向前向声明的类,但不能访问对象本身——此时编译器对对象的类或如何访问它一无所知

您需要将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("%dn", 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;)不是完整的定义。

解决方案是移动函数定义,使整个类定义已经在作用域中。

最新更新