C++编译报错C2512: vgui::EditablePanel无默认构造函数问题求助
问题原因与解决方案
你当前的核心设计思路有误:CMyPanelInterface是对外暴露功能的接口代理类,本身不需要也不应该继承VGUI的EditablePanel控件类。你要使用的SetControlInt属于VGUI控件成员方法,而你已经编写的CMyPanel类继承自vgui::Frame,Frame本身的继承链就包含EditablePanel,完全可以直接在CMyPanel内部调用SetControlInt。
编译错误逐一说明
vgui::EditablePanel无默认构造函数:EditablePanel的构造必须传入父面板指针、控件名两个参数,你没有在CMyPanelInterface的构造函数初始化列表里给父类传参,自然报错。- 抽象类无法实例化:你修改继承代码时破坏了
IMyPanel接口纯虚函数的匹配规则,导致三个接口方法没有被正确识别为重写,因此CMyPanelInterface变成抽象类,不能实例化全局对象g_MyPanel。
修正方案
直接删除CMyPanelInterface对EditablePanel的继承,把读取ConVar、调用SetControlInt的逻辑移到CMyPanel的Activate方法里即可,同时补全你代码里遗漏的控件初始化、空指针判断。
修正后的完整代码
//The following include files are necessary to allow your MyPanel.cpp to compile. #include "cbase.h" #include "IMyPanel.h" using namespace vgui; #include <vgui/IVGui.h> #include <vgui_controls/TextEntry.h> #include <vgui_controls/Frame.h> #include <vgui_controls/Button.h> #include <vgui_controls/EditablePanel.h> #include <vgui_controls/Checkbutton.h> //CMyPanel class: Tutorial example class class CMyPanel : public vgui::Frame { DECLARE_CLASS_SIMPLE(CMyPanel, vgui::Frame); CMyPanel(vgui::VPANEL parent); ~CMyPanel(){}; vgui::TextEntry* m_pTime; protected: virtual void OnTick(); virtual void OnCommand(const char* pcCommand); virtual void Activate() override; // 重写Activate方法处理控件值初始化 private: Button *m_pCloseButton; CheckButton *m_pCheckButton; ConVarRef m_r_newflashlight; // 把ConVarRef移到类成员避免重复定义 }; ConVar cl_showmypanel("cl_showmypanel", "0", FCVAR_CLIENTDLL, "Sets the state of myPanel <state>"); // Constuctor: Initializes the Panel CMyPanel::CMyPanel(vgui::VPANEL parent) : BaseClass(NULL, "MyPanel"), m_r_newflashlight("r_newflashlight") { SetParent(parent); SetKeyBoardInputEnabled(true); SetMouseInputEnabled(true); SetProportional(false); SetTitleBarVisible(true); SetMinimizeButtonVisible(false); SetMaximizeButtonVisible(false); SetCloseButtonVisible(false); SetSizeable(false); SetMoveable(true); SetDeleteSelfOnClose( true ); SetVisible(true); m_pTime = new vgui::TextEntry(this, "MyTextEntry"); m_pTime->SetPos(15, 310); m_pTime->SetSize(50, 20); m_pCloseButton = new Button(this, "Button", "Close", this, "turnoff"); m_pCloseButton->SetPos(433, 472); m_pCloseButton->SetDepressedSound("common/bugreporter_succeeded.wav"); m_pCloseButton->SetReleasedSound("ui/buttonclick.wav"); // 补全CheckButton的初始化,原代码未实例化就调用SetPos会引发崩溃 m_pCheckButton = new CheckButton(this, "r_newflashlight", "启用新手电筒"); m_pCheckButton->SetPos(200, 200); SetScheme(vgui::scheme()->LoadSchemeFromFile("resource/SourceScheme.res", "SourceScheme")); LoadControlSettings("resource/UI/mypanel.res"); vgui::ivgui()->AddTickSignal(GetVPanel(), 100); DevMsg("MyPanel has been constructed\n"); } void CMyPanel::Activate() { BaseClass::Activate(); // Frame本身继承自EditablePanel,可直接调用SetControlInt if (m_r_newflashlight.IsValid()) { SetControlInt("r_newflashlight", m_r_newflashlight.GetInt() ? 1 : 0); } } //Class: CMyPanelInterface Class. Used for construction. class CMyPanelInterface : public IMyPanel { private: CMyPanel *MyPanel; public: CMyPanelInterface() { MyPanel = NULL; } void Create(vgui::VPANEL parent) override { MyPanel = new CMyPanel(parent); } void Destroy() override { if (MyPanel) { MyPanel->SetParent((vgui::Panel *)NULL); delete MyPanel; MyPanel = NULL; } } void Activate(void) override { if (MyPanel) { MyPanel->Activate(); } } }; static CMyPanelInterface g_MyPanel; IMyPanel* mypanel = (IMyPanel*)&g_MyPanel; void CMyPanel::OnTick() { BaseClass::OnTick(); SetVisible(cl_showmypanel.GetBool()); } CON_COMMAND(ToggleMyPanel, "Toggles myPanel on or off") { cl_showmypanel.SetValue(!cl_showmypanel.GetBool()); mypanel->Activate(); }; void CMyPanel::OnCommand(const char* pcCommand) { BaseClass::OnCommand(pcCommand); if (!Q_stricmp(pcCommand, "turnoff")) cl_showmypanel.SetValue(0); }
额外优化说明
- 给
CMyPanelInterface的三个接口方法加上override关键字,确保编译器能正确识别是重写接口的纯虚函数,避免抽象类错误 - 把
r_newflashlight的ConVarRef改为CMyPanel的成员变量,避免重复定义 - 补全了
m_pCheckButton的初始化代码,避免运行时空指针崩溃 - 将控件值初始化逻辑移到
CMyPanel的Activate方法中,符合VGUI控件的设计规范
内容的提问来源于stack exchange,提问作者Roundabout9
相关产品推荐
相关产品推荐

