0

The title of the question is not very clear, I'll try to explain better. I'm using Qt and the windows I'm working with derive (directly or indirectly) from QWidget. My windows has to be treat uniformly, so that I can take a pointer to the currently active window and invoke methods on it not knowing the actual window class, for this reason all my windows derive from another class, let's call it "myScreen". So far so good.

Now I would like to handle in "myScreen" also the hiding and showing of a window, so that it's uniform. For example passing from a window to another may imply calling "hide()" on the current window and "show()" on the new window. Since "myScreen" and QWidget don't have any relationship, I must use dynamic_cast to cast the windows that I know derive from "myScreen" and "QWidget" inside "myScreen" methods, in order to call the functions of QWidget just mentioned.

I know that probably the best way could be having "myScreen" derive from QWidget and all of other windows derive from that, but my goal is to change as little as possible the existing code. I also tried using virtual inheritance, but this approach can't work because of the files generated automatically by the moc (see this link Cannot convert from pointer to base class to pointer to derived class).

By now I managed to ensure that a constructor of "myScreen" is called by a class that derives from QWidget:

struct isQWidget{
    class QWidgetType{
        QWidgetType(){}
        friend struct isQWidget;
    };
    template<class T>
    static QWidgetType isQwidgetType(const T&){
        static_assert (std::is_base_of<QWidget, T>::value, "Error: not a QWidget");
        return QWidgetType();
    }
};

Constructor declaration:

myScreen(myScreen& parentScreen, isQWidget::QWidgetType);

Constructor definition:

sigin::sigin(QWidget *parent, myScreen& si) :
    QWidget(parent),
    myScreen(si, isQWidget::isQwidgetType(*this)),
    ui(new Ui::sigin)
{
    ui->setupUi(this);
}

I would like to treat a pointer to myScreen as a pointer to QWidget inside "myScreen" compile-time, since I know I will always use something that derives from QWidget.

Any idea on how I can manage this problem?

Zack
  • 117
  • 1
  • 11
  • "I must use dynamic_cast" - yes, that seems like the way to do it. What's the specific problem you're having with this existing solution? See also: https://stackoverflow.com/questions/7426422/multiple-inheritance-casting-from-base-class-to-different-derived-class – John Zwinck Apr 26 '20 at 10:42
  • There is no "problem" in the real sense of the word, it works; I just don't like that I must use dynamic cast even if I know that "myScreen" subclasses derive from QWidget. I'm searching for a better way of arranging things, but with minimal change to the existing window classes. – Zack Apr 26 '20 at 10:50
  • If you want to have *static* check in place of usage, you should be using template constructor for `myScreen` parameterized by the parent type. – max630 Apr 26 '20 at 11:09
  • @max630 Can you explain better? How will I use inside my `myScreen` `this` as pointer to `QWidget`? – Zack Apr 26 '20 at 14:16
  • Do your concrete classes have multiple inheritance from `QWidget` and `myScreen`? – max630 Apr 27 '20 at 10:57
  • @max630 With this solution, yes – Zack Apr 27 '20 at 15:01

1 Answers1

0

I had something like this in mind

template <typename T>
myScreen::myScreen(T &parent)
{
    static_assert(std::is_base_of<QWidget, T>::value, "Error: not a QWidget");
    QWidget &parentQt = dynamic_cast<QWidget&>(parent); // guaranteed to succeed in runtime by the above
    ...
}

So for parent which does not inherit from QWidget that would be a compilation error, and which does would always cast successfully.

max630
  • 8,762
  • 3
  • 30
  • 55
  • But how can I use `this` as it is was a QWidget*? I want to avoid the usage of dynamic_cast at all. With the code I have I am already sure that the class I am calling the constructor from is deriving also from QWidget. – Zack Apr 27 '20 at 08:53
  • Well actually id you have T you can already use the `parent` directly – max630 Apr 27 '20 at 10:58
  • if static_assert is not enough you may use constexpr if, that should work for sure – max630 Apr 27 '20 at 11:00
  • well with the template, you don't even have to make assert, because of template lazyness – max630 Apr 27 '20 at 11:14
  • Ok, but I am interested to use `this` as it was a QWidget*, so for example write `this->hide()` in other methods of `myScreen`. With templates I can do this on parent, but not on `this`... probably the virtual inheritance is the only way, but I can't use it. – Zack Apr 27 '20 at 15:13