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

时间:2015-04-26 06:56:14

标签: c++ forward-declaration dereference

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

如果我尝试读取/打印这些值,它将无法编译并将给出错误C2027:使用未定义类型' BassMusicPlayer '。我还根据其他人的建议将静态添加到类定义中。我可以使用全局变量作为解决方法,但我真的想避免这样做。

这就是我在班级文件中的内容:

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类只有在我想访问其变量时才被识别?

3 个答案:

答案 0 :(得分:1)

在您定义LoopSyncProc的代码中的那一点,您只是声明了BassMusicPlayer。你告诉编译器:&#34;有一个名为BassMusicPlayer&#34;的类,仅此而已。

您可以使用指向前向声明的类的指针,但是您无法访问该对象本身 - 此时编译器对该对象的类没有任何了解,或者如何访问它。

您需要将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
}

答案 1 :(得分:1)

您的BassMusicPlayer无法识别,因为您有:

class BassMusicPlayer;

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

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

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

代码的整体顺序应为:

  • 转发声明LoopSyncProc函数
  • 声明班级
  • 定义LoopSyncProc函数

答案 2 :(得分:0)

问题在于,在编译该函数时,类型尚未完全定义。裸声明(class BassMusicPlayer;)不是完整的定义。

解决方案是移动函数定义,以便整个类定义已经在范围内。