Problem with inheritance and QObject/QDialog
-
A colleague implemented an ABC (with some none abstract mfs) for a progress indicator base class. The idea being to implement a Qt subclass for AppA, a command line text based subclass for AppB and a different Qt subclass for AppC.
class ProgressDlg : public ProgressBase, public QDialog { Q_OBJECT private: Ui::ProgressDlg* ui;
This sort of worked until we wanted to change the code to have some base class function as slots at which point it all fell apart (because the Qt subclass was a QDialog (and therefore a QObject) and the base class was also a QObject (OOPS).
Is it as simple as removing "public QDialog" from the class definition and adding :
QDialog* theDialog as a private member, and then invoking:
ui->SetupUi(theDialog);
Or is there more I need to worry about?
Thanks
David -
A colleague implemented an ABC (with some none abstract mfs) for a progress indicator base class. The idea being to implement a Qt subclass for AppA, a command line text based subclass for AppB and a different Qt subclass for AppC.
class ProgressDlg : public ProgressBase, public QDialog { Q_OBJECT private: Ui::ProgressDlg* ui;
This sort of worked until we wanted to change the code to have some base class function as slots at which point it all fell apart (because the Qt subclass was a QDialog (and therefore a QObject) and the base class was also a QObject (OOPS).
Is it as simple as removing "public QDialog" from the class definition and adding :
QDialog* theDialog as a private member, and then invoking:
ui->SetupUi(theDialog);
Or is there more I need to worry about?
Thanks
DavidHi,
It looks like a case of trying to inherit every time (is a VS has a) rather than compose.
Rather than subclass that progress indicator class, why not compose a class with it and whatever you need to output the information ?
-
A colleague implemented an ABC (with some none abstract mfs) for a progress indicator base class. The idea being to implement a Qt subclass for AppA, a command line text based subclass for AppB and a different Qt subclass for AppC.
class ProgressDlg : public ProgressBase, public QDialog { Q_OBJECT private: Ui::ProgressDlg* ui;
This sort of worked until we wanted to change the code to have some base class function as slots at which point it all fell apart (because the Qt subclass was a QDialog (and therefore a QObject) and the base class was also a QObject (OOPS).
Is it as simple as removing "public QDialog" from the class definition and adding :
QDialog* theDialog as a private member, and then invoking:
ui->SetupUi(theDialog);
Or is there more I need to worry about?
Thanks
David@Perdrix said in Problem with inheritance and QObject/QDialog:
This sort of worked until we wanted to change the code to have some base class function as slots at which point it all fell apart (because the Qt subclass was a QDialog (and therefore a QObject) and the base class was also a QObject (OOPS).
I am not entirely sure, but it might be that the Qt class needs to be the first class in the inheritance hierarchy. Try swapping ProgressBase and QDialog.
Having QDialog as a member instead is also a solid way to go. That should work perfectly fine without any further problems.
-
Maybe one more thought: You mentioned that one of the apps is command line based. For the most general case of a progress indicator I'd usually use a callback function. Then I could get rid of the ProgressBase base class altogether. Callback functions should have a void pointer to carry any user-defined load in addition to the progress itself. In your example the void pointer could point to your progress dialog and trigger according calls.
-
Maybe one more thought: You mentioned that one of the apps is command line based. For the most general case of a progress indicator I'd usually use a callback function. Then I could get rid of the ProgressBase base class altogether. Callback functions should have a void pointer to carry any user-defined load in addition to the progress itself. In your example the void pointer could point to your progress dialog and trigger according calls.
@SimonSchroeder A very short example of what you have in mind would be most helpful
-
@SimonSchroeder A very short example of what you have in mind would be most helpful
@Perdrix said in Problem with inheritance and QObject/QDialog:
A very short example of what you have in mind would be most helpful
I assume that this is in response to callback functions.
Basically, you would have two functions: one for registering a callback with its associated data and the other to call the callback. For simplicity I'll assume there will only be one single callback at a time and I'll use global data. It is easy to make this a little nicer.
void (*progressCallback)(int progress, void *data) = nullptr; void *progressCallbackData = nullptr; void registerProgressCallback(void (*callback)(int progress, void *data), void *data) { progressCallback = callback; progressCallbackData = data; } void updateProgress(int progress) { if(progressCallback) { progressCallback(progress, progressCallbackData); } } class MyProgressClass { public: MyProgressClass() { registerProgressCallback(std::mem_fun(&MyProgressClass::updateProgress), static_cast<void*>(this)); } void updateProgress(int progress) { //... } };
This would be the rough outline for using callbacks. I am not entirely sure about
std::mem_fun
(or is itstd::mem_fn
now?). Maybe you need an additional wrapper function to cast the void pointer back to a pointer to MyProgressClass. Maybe lambdas would work as well. Things look a little easier if you don't use a function pointer butstd::function<void(int,void*)>
instead. I am also not entirely sure if I got the function pointer syntax right.registerProgressCallback() and updateProgress() could also be static functions of a class together with class variables storing all callbacks and their associated data in vectors.
The advantage of the void pointer for additional data is that you can just declare a struct and put all function parameters into this. Then write a wrapper function that will unwrap the data from the struct and call you progress function with an arbitrary amount of (fixed) parameters.