c++ 在非类函数中使用类变量

c++ Use a class variable in a non-class function

本文关键字:类变量 类函数 c++      更新时间:2023-10-16

我正面临这个新手问题。假设类MainFrame(以下代码不会编译 - 我试图给出我正在做什么的基本概念,因为我认为我的问题很容易由比我知识渊博的人解决(,它与其他函数一起存在于文件gui.cxx中。请注意,这是一个更大项目的一部分,所以我跳过了我包含在gui.h的main.cxx。

在函数start_gui_with_config()中,我尝试使用来自MainFrame的对象。目前被宣布为private,所以我期待有一个text_data_path was not declared in this scope.

我还在gui.h年的类定义中将此变量声明为publicstatic,但随后在使用任一text_data_path ->SetText(data_path);时出现相同的错误。

当我使用MainFrame::text_data_path ->SetText(data_path);时(仍然text_data_path被声明为privatestatic(,我在MainFrame::MainFrame构造函数(文件gui.cxx(中使用text_data_path的任何行中都收到错误undefined reference to MainFrame::text_data_path,奇怪的是,我每行都收到此错误两次。

最后,我尝试将所有函数(start_gui()start_gui_with_config()(作为MainFrame的一部分,并将它们声明为static void(在这种情况下,我得到了一个错误错误:无法声明成员函数静态void MainFrame::start_gui_with_config((在gui.cxx上具有静态链接(或void(在这种情况下,我得到了错误错误: 不能调用成员函数 void 大型机::start_gui_with_config((main.cxx上没有对象(。

关于如何在函数中使用text_data_path的任何想法(即start_gui_with_config()(不属于该类?

GUI.cxx

#include "../include/gui.h"    
MainFrame::MainFrame(const TGWindow *p, UInt_t width, UInt_t height):TGMainFrame(p, width, height, kMainFrame|kHorizontalFrame){
// Define widgets
text_data_path = new TGTextEntry("/data/2020");
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// This is a virtual constructor
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
MainFrame::~MainFrame() {
// Clean up used widgets: frames, buttons, layout hints
Cleanup();
}//_____MainFrame::~MainFrame()
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// This is to start the GUI with default settings
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
void start_gui(){
// Popup the gui
std::cout << "Starting the gui" << std::endl;
new MainFrame(gClient->GetRoot(), 1000, 800);
}//_____start_gui()
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// This is to start the GUI using the configuration file from previous session
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
void start_gui_with_config(){
TString data_path = gSystem->GetFromPipe("awk '{if(NR==1) print $NF}' Config/last_session.cfg.viewer");

start_gui();

MainFrame::text_data_path->SetText(data_path);

}//____MainFrame::start_gui_with_config()

桂·

#ifndef ___GUI_H
#define ___GUI_H
//ROOT Includes
#include <TGTextEntry.h>
//C++ includes
using namespace std;
class MainFrame : public TGMainFrame {
private:
// Widgets
TGTextEntry         *text_data_path;

public:
// Widgets
//static TGTextEntry         *text_data_path;
MainFrame(const TGWindow *p, UInt_t width, UInt_t height);
virtual ~MainFrame();
//void start_gui_with_config();
//static void start_gui();
ClassDef (MainFrame,0);// Remove for ROOT6 and rootcling
};
void start_gui();
void start_gui_with_config();
#endif

我建议你在MainFrame类上使用二传手:

void setDatapathText(TString const& newDatapath) { 
text_data_path->SetText(data_path);
}

然后你可以在start_gui_with_config函数中这样调用它:

auto frame = MainFrame(p, w, h);
frame.setDatapathText(data_path);

请注意,您的代码显然存在内存管理问题,作为一般规则,您永远不应该在智能指针之外处理原始newdelete。我建议您确保对动态分配感到满意,否则恐怕您将比预期更早地面临难以调试的错误

您的问题是您丢弃了指向MainFrame的指针,因此在创建大型机后无法在start_gui_with_config()中访问它。

解决此问题的一种方法是将void start_gui();的签名更改为gui.h标头中的MainFrame* start_gui();

gui.cxx将实现更改为

MainFrame* start_gui() {
return new MainFrame(gClient->GetRoot(), 1000, 800); 
}

然后在您的start_gui_with_config()中像这样使用指针:

void start_gui_with_config(){
TString data_path = gSystem->GetFromPipe("awk '{if(NR==1) print $NF}' Config/last_session.cfg.viewer");

MainFrame* frame = start_gui();
frame->text_data_path->SetText(data_path);

}//____MainFrame::start_gui_with_config()

此代码假定 MainFrame 对象自行销毁,否则代码将泄漏内存。我假设这种破坏发生在窗口关闭后。我已经看到其他像Qt这样的GUI框架这样做。