【问题标题】:illegal reference to non-static member or unresolved external symbol非法引用非静态成员或未解析的外部符号
【发布时间】:2012-01-03 18:51:35
【问题描述】:

我正在尝试使用 wxWidgets 学习 c++。到目前为止,我所有的程序都是用纯 C(不需要对象)、vba、bash 编写的——正如你所见,我不是程序员。

即使这个例子在 wxWidgets 框架中,它也是一般的 c++ 问题(实际上这是我的 c++ 问题;-)

主窗口有一个带有子菜单设置/通信的菜单栏。 我在 startup.h 中为主框架定义了一个类:

class startUp: public wxFrame
{    
    DECLARE_CLASS( startUp)
    DECLARE_EVENT_TABLE()
public:
    startUp();
    startUp( wxWindow* parent, wxWindowID id = SYMBOL_....
    ~startUp();
    void OnMENUCommunicationClick( wxCommandEvent& event );
    ....
    void SetDevName(const wxString& devname);
protected:
    static wxString devName;
};

startup.cpp

....
void startUp::SetDevName(const wxString& devname) 
{
    devName=_T(devname);
}

OnMENUCommunicationClick 调用一个对话框,该对话框应该返回在 wxChoice 中选择的设备的名称(顺便说一句,wxChoice 工作的馈送)。此对话框在另一个类中定义:

#include "startup.h"
class Communication: public wxFrame
{  
....
void Communication::CreateControls();
protected:
    wxArrayString portChoiceStrings;

通信.cpp:

...
void Communication::CreateControls()
    std::vector<std::string> ports;
    int count = ScanSerialPorts( ports, true );
    for( int i = 0; i < count; i++ ) {
       portChoiceStrings.Add( wxString( ports[ i ].c_str(), wxConvUTF8 ) );
    }
    portChoice = new wxChoice( itemPanel2, ID_ComportSet, wxPoint(108, 25), wxSize(55, -1), portChoiceStrings, 0 );
    portChoice->SetSelection(0);
....
}

void Communication::OnOKClick( wxCommandEvent& event )
{
    startUp::SetDevName(_T(portChoiceStrings[portChoice->GetSelection()]));
    //startUp::SetDevName(wxT(""));
    Destroy();
}

现在我的问题是我希望 OnOKClick 会返回到 startUp 选择的设备。我所拥有的是: c2352 非法调用非静态成员函数。由于 startUp 的成员未初始化,我的选择是在 startup.h 中将函数和变量都更改为静态。

static void SetDevName(const wxString& devname);
static wxString devName;

情况有所改善 - 所有文件都可以编译,但链接器显示未解析的外部符号“受保护:静态类 wxString startUp::devName”。将 devName 从受保护移动到公共不会改变任何事情。

谁能解释一下在类之间传递值的“正确”方式是什么?我不想使用全局变量来解决它。显然这些都是邪恶的。

【问题讨论】:

    标签: c++ wxwidgets


    【解决方案1】:

    我找到了解决方案。我已经从定义中删除了 static 这个词。

    在初始化对话框窗口后的类 startup 中,我添加了对函数 setLink 的调用:

    void startUp::OnMENUCommunicationClick( wxCommandEvent& event )
        {
        Communication* window = new Communication(this,ID_COMMUNICATION, _("Communication Settings"));
        window->setLink(this);
        int returnValue = window->Show();
        }
    

    比在类Communication中我添加了一个链接函数setLink,它存储了主窗口的指针:

    void Communication::setLink(startUp* papi)
        {
        this->m_link = papi;
        }
    

    我可以在 OnSetClick 中使用它:

    void Communication::OnSetClick( wxCommandEvent& event )
        {
        m_link->SetDevName(_T(portChoiceStrings[portChoice->GetSelection()]));
        Destroy();
        }
    

    m_link 变量在 communication.h 中定义为 startUp 类的成员:

    startUp* m_relative;   
    

    一切正常(程序编译和链接没有错误,并且 startUp-Frame 中的 devName 变量设置为从通信菜单读取的值。

    【讨论】:

    • 这是一种方式(对话框在关闭前推送值)。如果你的对话框是非模态的,你必须有某种类似的链接。 otoh,如果您的对话框是模态的,那么您的框架对象显示它可能更有意义,然后在它返回结果时从中读取值。两种方法都有效。我更愿意将链接传递给对话框的构造函数,因为这表明对话框需要链接才能正常执行。
    猜你喜欢
    • 2017-10-06
    • 2020-04-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多