Access function variables between friend classes - c++

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
}

Related

How to access variable between classes

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.

MFC Current class as argument

I have created the following MFC program :
CMyClass is the class, it has one CString member called "m" and one method called "MyFunc". I would like to pass the current class as argument for my method.
In the header file:
public:
CString m;
void MyFunc(CMyClass CM)
In the cpp file:
//Button event
void CMyClass::OnBnClicked()
{
m = _T("");
MyFunc(this);
//MessageBox displaying the updated "m" member
MessageBox(m,_T(""),MB_ICONINFORMATION);
}
//Method updating the member m
void MyFunc(CMyClass CM)
{
CM.m = _T("TEST");
}
The button click function updates the member "m" of the class and display the new "m" value but it does not change.
I would like to know why the argument "this" has not been properly passed. Is something wrong with my code ?

Passing QObject with Pointer (Qt)

My goal is to pass the windowobject pointer to another class.
I'll show you what i got so far.
where: "dialog" is the window to pass.
mainwindow.cpp
dialog = new Dialog(this);
someClass(dialog);
Konstruktor in someClass
someClass::someClass(Dialog *d)
{
Dialog *dia = d;
}
someClass.h
#include "dialog.h"
...
public:
someClass(Dialog *dialog)
//Dialog d;
The program runs now, but i'm not sure if i achieved what i wanted.
Is it possible to interact with my dialog now?
What i want is something like this.
dia->ui->lineEdit->setText();
Any help would be appriciated
someClass(&dialog);
is incorrect ... you have a pointer and give the address of the pointer (a pointer to the pointer) in the function
also you have
Dialog d;
in your header and assigning a Dialog* to it.
I recommend you to have a look at: The Definitive C++ Book Guide and List
My goal is to pass the windowobject pointer to another class. I'll
show you what i got so far. where: "dialog" is the window to pass.
considering your code:
someClass::someClass(Dialog *d)
{
Dialog *dia = d;
}
is a local member in the constructor someClass. Therefore it only has scope in the constructor itself (is not visible outside of the constructor, and in fact, does not live outside of the constructor (is destroyed when the constructor goes out of scope)).
Fortunately dia is a pointer (address of object), and not the actual dialog (therefore only the pointer, and not the object that it points to goes out of scope). If you want the pointer to remain in scope for the purpose of access later on, you have to "tie" it to the scope of the class (make it a class member).
class MyClass
{
public:
//Using reference as it may not be null...
MyClass( Dialog& dialog );
void showDialog();
private:
//We only want to expose a small part of dialog to users,
// hence keep it private, and expose what we want through
// the interface (the public part).
Dialog& dialog_;
};
//MyClass.cpp
MyClass::MyClass( QPointer<Dialog> )
: dialog_( dialog ) //Google "member initialisation"
{
}
void MyClass::showDialog(){ dialog_.show(); }
----- Modified/Additional answer -----
If in the above example dialog_ is optional, then you needn't make it a reference member, as reference members require to be initialised (one cannot have an uninitialised reference). In that case, make it a pointer... When using Qt, I would make it a QPointer (Assuming Dialog is a QObject), as QPointers are safer to work with than raw pointers (They are always initialised to zero, at least).
I'll show you the basic principle to keep it simple for now. Read up about QPointers and smart pointers in general.
e.g:
class MyClass
{
public:
// May or may not hold zero...
explicit MyClass( Dialog* dialog = 0 );
void showDialog();
private:
//We only want to expose a small part of dialog to users,
// hence keep it private, and expose what we want through
// the interface (the public part).
Dialog* dialog_;
};
//.cpp
MyClass::MyClass( Dialog* dialog /* = 0*/ )
: dialog_( dialog )
{
}
void MyClass::showDialog()
{
if( dialog_ )
{
dialog_->show();
}
else
{
std::cout << "This is in fact not a dialog"
"\nbut be so kind as to enter"
" whatever you want here ;-)"
<< std::endl;
while( !terminated() )
{
std::string inputStr;
std::cin >> inputStr;
evalute( inputStr );
}
}
}
We don't know what your Dialog class looks like, but if its member ui is public (or someClass is a friend of Dialog), then you should be able to do
dia->ui->lineEdit->setText();
Do you get any compiler errors? Or does the text simply not show up as expected?
You would still need to show the dialog at some point using
dia->show();
or
dia->exec();

Accessing member variables of MFC dialog in non-member function

I'm working on a MFC dialog and I'm not sure how to access object's member variables (Edit controls, buttons, check boxes, etc) from a non-member function.
Since the object is created in whatever.cpp, and all the object events are handled in whateverDlg.cpp, and the latter #include's the former, I can't access Dlg's members by conventional means.
Example for clarification:
void BlahDlg::OnBnClickedblah()
{
//...
CString text = L"blahblahblah";
m_bEditControl.SetWindowTextW(text.GetBuffer()); //works fine
//...
}
void nonMember()
{
//...
CString text = L"blahblahblah";
m_bEditControl.SetWindowTextW(text.GetBuffer()); //m_bEditControl is unknown
//...
}
In other words: What should I do to access m_bEditControl (or any other dialog's member) from the non-member function?
If you want to keep GUI separated from logic, then you can keep your dialog class very thin, basically just for recognizing events that occur (onBtnSomethingClick, onPaint, onCancel, etc.) and create a class that will be responsible for handling these events once they occur.
One of the simplest possible solutions would be to construct this kind of class by passing your dialog by reference to its constructor:
class MyClass
{
public:
MyClass(MainDlg& dlg) : dlg_(dlg) { }
private:
MainDlg& dlg_;
};
And your dialog class could instantiate object of your class:
class MainDlg : public CDialog
{
public:
BOOL MainDlg::OnInitDialog()
{
//...
myClass_ = new MyClass(*this);
return TRUE;
}
~MainDlg()
{
//...
delete myClass_;
}
private:
MyClass* myClass_;
};
Just don't "spread" references to any GUI classes any further. If you need to directly access some members of your dialog, then you might consider redesigning your code - for example if you are writing method for creating new Users and you are thinking about accessing some text field of your dialog, then it seems to be much better idea, to "collect" input from dialog members and pass it to this kind of function independantly from your dialog class.
To your problem: if you have a helper non-member function that needs to use dialog's CEdit member, then you can change void nonMember() to void nonMember(CEdit& m_bEditControl) and pass the reference to this member when calling it in member function: nonMember(m_bEditControl); But note that that kind of approach is wrong.
In other words: this seems to be a bad design:
void nonMember(CEdit& m_bEditControl)
{
CString text = L"something";
m_bEditControl.SetWindowTextW(text.GetBuffer());
}
void MainDlg::someMethod()
{
nonMember(m_bEditControl);
}
and this seems to be much better:
CString nonMember2()
{
return L"something";
}
void MainDlg::someMethod()
{
CString str = nonMember2();
m_bEditControl.SetWindowTextW(str.GetBuffer());
}
Hope this helps :)

c++ Setting a pointer variable in parent class from child and use it in parent class

i'm sorry for the title. I seem to have a problem. I'm just a beginner and i'm sorry if this was asked before.. i couldnt find a straight answer on this one. (when i search class, pointer and child i get results about passing parent or child pointers... i do not want to pass the (this) child or parent pointer, i just want to pass a pointer i initialized on a child class.. to the parent). What i'm trying to do here is better explained by code:
class App
{
public:
virtual void init(void) { window = &BasicWindow(); }
virtual void createWindow(void) { window->create(); }
protected:
Window *window;
};
class Game : public App
{
public:
virtual void init(void) { window = &OpenGLWindow(); }
};
int main ()
{
App *game = &Game();
game->init();
game->createWindow();
return 0;
}
Is this legal?
I have an abstract Window class from which BasicWindow and OpenGLWindow derives.
However, when i create the window i get an Access violation reading location error breaking at window->create() inside the App::createWindow() function.
Thanks
I'm guessing this is because you are pointing to a temporary:
window = &BasicWindow()
Once that function exits, window points to "crap" and bad things will happen.
presumably, what you want to do is to create a new instance of the window - i.e.
window = new BasicWindow();
Don't forget to cleanup!
I'm going to take a punt that you're coming from Objective-C? ;)
I think your problems all stem from not understanding how C++ objects are created.
First up: window = &BasicWindow(); is not how you should be creating a new object. You need to use window = new BasicWindow; This results in space for a BasicWindow being allocated in memory, and the default constructor for BasicWindow will be invoked.
Your have a similar error in your main() method, however in this case you do not need to use new to allocate it, you can just declare an instance and it will be created on the stack.
Your main method would then look like:
int main ()
{
Game game;
game.createWindow();
return 0;
}
The remaining problem is that your init methods are not being called. In C++ constructors are called automatically, and are named the same name as the class. An example default constructor for the game class would be:
Game() { window = new OpenGLWindow(); }
Another thing you need to know is that, unlike objective C, the entire hierarchy of constructors is called automatically when you create an object. That is, when you create an instance of Game, its constructor is called, as well as the constructor of every base class. In fact, the base class constructor is called FIRST. So in your case, if you just change the init methods to constructors, you'll allocate two windows (one of each type) and leak the BasicWindow. Which is not cool.
You should probably just leave them named init, and just make sure you call it immediately after creation.
In summary, try this:
class App
{
public:
virtual void init(void) { window = new BasicWindow; }
virtual void createWindow(void) { window->create(); }
protected:
Window *window;
};
class Game : public App
{
public:
virtual void init(void) { window = new OpenGLWindow; }
};
int main ()
{
Game game;
game.init();
game.createWindow();
return 0;
}
(and don't forget to cleanup the new'd objects!)
EDIT (added example complete with cleanup):
class App
{
public:
App() : window( NULL ) {}
virtual ~App() { delete window; }
virtual void init() { window = new BasicWindow; }
virtual void createWindow() { window->create(); }
protected:
Window *window;
};
class Game : public App
{
public:
virtual void init() { window = new OpenGLWindow; }
};
int main ()
{
Game game;
game.init();
game.createWindow();
return 0;
}
window is an uninitialized pointer of class App. Because, no where you are calling init method. So, window->create() results error, when base class createWindow() is called.
Edit 1:
As far as now, every thing is syntactically correct but amn't sure of what you are trying to achieve. Don't create temporary/nameless objects and assign them. Instead construct them with operator new in window = &BasicWindow(); and window = &OpenGLWindow();. Since the class manages resources, you should follow the principle Rule of Three. Also know that in statement -
App *game = new Game();
The static type of operand ( App* ) is different from the dynamic type( Game*). In such a case, the static type acts as a base class and it's destructor must be virtual or else the behaviour is undefined. So, the App class destructor must be virutal.
The error might be related to the fact that you are using pointers to temporaries.
virtual void init(void) { window = &BasicWindow(); }
This pointer becomes invalid after the ";". Use "new" instead of "&".
You need to call game->init() if you want to use the window pointer too (Even better put in in a constructor, thats what they are for).
Besides that, it is perfectly legal to change protected members of base classes.