How to access variable between classes - c++

Just have a question. I am trying to display a filename in a message box. This file name is part of a full path. I need to set the path using a Set method in CChooseDirDlg class and call this in SecondDlg class using a Get method. Both classes are declared as friends but are in different files. However, the message box is returning nothing. Any ideas? Thankyou for your time...
ChooseDirDlg.h
class CChooseDirDlg : public CDialog
{
// Construction
friend class SecondDlg;
public:
CString sPath;
ChooseDirDlg.cpp:
void CChooseDirDlg::SetPath(CString path){
path = m_DirTree.GetCurrentDir(); //find path
sPath = path;
}
CString CChooseDirDlg::GetPath(){
return sPath;
}
SecondDlg.cpp:
void SecondDlg::OnOK()
{
CChooseDirDlg dlg;
dlg.SetPath(path); // set path
dlg.GetPath(); // get path
char drive[_MAX_DRIVE];
char dir[_MAX_DIR];
char fname[_MAX_FNAME];
char ext[_MAX_EXT];
// Split path to isolate filename
_splitpath(dlg.GetPath(), drive, dir, fname, ext);
AfxMessageBox(fname);
}

Your code don't show where you set the path, but I'm going to presume that this is done somewhere that is not inside the OnOk scope.
The line:
CChooseDirDlg dlg;
in your OnOk method means that you are creating a local instance of the CChoseDirDlg class.
This instance does not share the value of member variables (if they are not static) with other instances of the class, so if you call SetPath on another instance, the dlg instance in the OnOk scope will not have the data.

Related

QT Creator accessing pointers to objects

Very new to QT but basically I have a class called object and on my GUI is a one button and one text browser. Now in my class object I have one private QString variable called name and its constructor assigns a value (QString) to the variable called name . The object class has one function called QString getName() const; which returns the name:
class object{
private:
QString name;
public:
object(QString name);
QString getName()const;
};
Now in QT in my mainwindow.h file I put
public:
object *o;
and then in the constructor :
object o2("Name");
o = &o2;
Now I want to call the function void MainWindow::on_pushButton_clicked() and all this function will do is set the text in the text browser to the name variable in my object (which would be "Name" btw) so inside the function I put ui->Console->setText(o->getName()); console being the name of my text browser- when i run the code and click the button its saying that Ive referenced memory and giving an error. Keep in mind I moved ui->Console->setText(o->getName()); to the constructor and it worked perfectly (obviously didnt work when the button was clicked but the text was put in the text browser) so what am I doing wrong here ?
The pointer (o) outlives the object that it points to (o2). One way to fix it is by allocating new memory for the object:
o = new object("Name");
And then you'll need to remember to delete that memory later.

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

I'm facing this novice issue. Assume the class MainFrame (the following code isn't going to compile - I'm trying to give a basic idea of what I'm doing because I think my problem is easy to solve by someone more knowledgeable than me) which lives on file gui.cxx along with other functions. Note that this is part of a larger project so I'm skipping the main.cxx which I have included gui.h.
In the function start_gui_with_config() I'm trying to use an object from MainFrame. At the moment is declared as private so I'm expecting to have an text_data_path was not declared in this scope.
I also declared this variable as public and static in the class definition in gui.h but then I get the same error when using either text_data_path ->SetText(data_path);.
When I'm using MainFrame::text_data_path ->SetText(data_path); (still text_data_path is declared as private and static) I get the error undefined reference to MainFrame::text_data_path in any line I'm using text_data_path within the MainFrame::MainFrame constructor (file gui.cxx) and strangely I get this error twice for each line.
Finally I tried making all the functions (start_gui(), start_gui_with_config()) part of MainFrame and I declared them as either static void (in this case I got an error error: cannot declare member function static void MainFrame::start_gui_with_config() to have static linkage on the gui.cxx ) or void (in this case I got the error error: cannot call member function void MainFrame::start_gui_with_config() without object on the main.cxx).
Any idea on how to use text_data_path in a function (i.e. start_gui_with_config()) that doesn't belong to the class?
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()
gui.h
#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
I suggest you use a setter on the MainFrame class:
void setDatapathText(TString const& newDatapath) {
text_data_path->SetText(data_path);
}
You can then call it like so in your start_gui_with_config function :
auto frame = MainFrame(p, w, h);
frame.setDatapathText(data_path);
Be careful, your code clearly has memory management problems, and as a general rule you should never deal with raw new and delete outside of smart pointers. I suggest making sure you are comfortable with dynamic allocation, else I'm afraid you will be facing hard-to-debug errors earlier than expected
Your problem is you throw away the pointer to your MainFrame so you have no way to access it in start_gui_with_config() after you created the MainFrame.
One way to fix this is to change the signature of void start_gui(); to MainFrame* start_gui(); in your gui.h header.
In the gui.cxx change the implementation to
MainFrame* start_gui() {
return new MainFrame(gClient->GetRoot(), 1000, 800);
}
And then in your start_gui_with_config() use the pointer like this:
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()
This code assumes the MainFrame object destroys itself otherwise the code will leak memory. I assume this destruction happens after the window closes. I have seen other GUI frameworks like Qt do this.

QT calling functions in different sources

In my project I've created multiple gui pages. In a secondary source (secondary.cpp) I want to call a function that declared in my mainwindow.cpp. I'm not really sure how to do this.
I've tried to declare the function at public section like:
QString format (QString number);
And definition in the mainwindow.cpp like:
QString MainWindow::format(QString number)
{
...
}
Then i include #include "mainwindow.h" in my secondary source (secondary.cpp) and calling the function with lower = format(upper); but I'm getting an error message:
format was not declared in this scope.
I've also tried calling it by
lower = MainWindow::format(upper);
which gives me the error message
Cannot call member function QString MainWindown::format(Qstring)
without object.
Finaly I also tried to make a class in my mainwindow.h
class test : public QString
{
public:
QString format (QString number);
};
With QString test::format(QString number) in my mainwindow.cpp calling the function by lower = test::format(upper);
this gives me the error:
Cannot call member function QString MainWindown::format(QString)
without object.
I'm not convinced that I need to create a new class, but I thought I'd try anyway.
You need to create object of MainWindow class, then call function:
MainWindow *w = new MainWindow;
QString lower = w->format(upper);
Or another solution is static function of class. This way you have no needed create object of class and can call method by name like this:
QString lower = MainWindow::format(upper);
Of course you need to include your #include "mainwindow.h" header.
But you should know that MainWindow class is not the best place storing function for formation string, you can use QString class function like QString::toUpper() or QString::toLower() or create your own class for formating:
class myFormatingStringClass {
QString toLower(QString str);
static QStrin toUpper(QString str);
}
As i said above this way you will need to create object of myFormatingStringClass for using myFormatingStringClass::toLower() function or using static method:
QString upper = QString("Hello World");
myFormatingStringClass formating;
QString lower = formatin.toLower(upper); // Using class method of existing object
QString upper = myFormatingStringClass::toUpper(lower); // Using static method
You can't do test::format(...) to call a non-static member function.
It must be bound to an object (an instance of your class). For example, you can do this :
test testObject;
QString formattedString = testObject.format(strToFormat);

Access function variables between friend classes

Just wondering...how can I access the variable 'path' of ClassA function Open() from within another fucntion of class ClassB if both classes are declared 'friends'? I'm basically trying to populate a child window with info from the parent window when the child window is selected, although both windows have different classes.
ClassA.cpp:
void ClassA::Open()
{
// Open Program Properties window
ClassB dlg;
dlg.DoModal();
CString path;
path = m_DirTree.GetCurrentDir(); //Path specified by tree selection
}
ClassB.cpp:
void ClassB::Display(){
//HOW CAN I ACCESS 'path' HERE?
SetDlgItemText(IDC_PATH, path); //Populate the edit box
}
Thankyou for the replies...
You pass an A object by reference (or any other way to make the object visible to B::Display) and just excess it with '.' operator
void ClassB::Display(A &a){
SetDlgItemText(IDC_PATH, a.path);
}
although you might want to consider exposing public set and get functions for these kind of variables
With your current code you can't.
After the function void ClassA::Open() your CString path; will be destroyed.
You could save your CString path; as member variable.
Or you could add a variable of CString to your function void ClassB::Display(), which could result in this code:
void ClassA::Open(void)
{
// Open Program Properties window
ClassB dlg;
dlg.DoModal();
CString path;
path = m_DirTree.GetCurrentDir(); //Path specified by tree selection
m_classBMember.Display(path);
}
void ClassB::Display(CString &path)
{
SetDlgItemText(IDC_PATH, path); //Populate the edit box
}

How can I find in C++ which child class is calling the function of the parent class?

I have a class A which has a function called openFile(const char * name), which opens a file.
I have two child classes Reader and Writer
Reader opens the file in a reading mode.
Writer opens the file in a writing mode.
I'm using fopen to open the file.
I would like to open this file in either a reading mode or a writing mode, depending on which child class is calling this method.
Is it possible to do this without sending any extra parameters to the parent class?
Of course, something like this is exactly what inheritance is meant to do:
class A {
public:
virtual void openFile(const char* name) = 0;
// If A cannot open a file on its own, else implement it
// rest of implementation
};
class Reader : public A {
public:
virtual void openFile(const char* name) {//open file in read mode}
//rest of implemenation
};
and handle Write analog. Then, given a pointer or reference of type A* or A& pointing or referring to one of the children, the right function will be chosen:
A* a1 = new Reader{};
A* a2 = new Writer{};
a1->openFile("test.in"); // calls Reader.openFile()
a2->openFile("test.out"); // calls Writer.openFile()