- 1. Hallo Vorlagen
- 1.
- 2. Echter Code:
Geben Sie das Lösch-Idiom ein
Der Artikel geht davon aus, dass der Leser über Grundkenntnisse in C++ verfügt
Direkt auf den Punkt.
Angenommen, Sie müssen den Text dynamisch (wie ich auf Knopfdruck) ändern
mehrere Objekte wie:
- QLabel
- QDrucktaste
- QLineEdit
Die meisten von Ihnen wissen, dass diese Widgets von QWidget erben. Warum also nicht eine Methode deklarieren, die einen Zeiger auf diese Basisklasse nimmt, und dann die Methode setText aufrufen?
QWidget * base_pointer = new QLabel(); base_pointer->setText("ERROR");
Das Problem ist, dass QWidget die Methode setText() nicht definiert, also können Sie das nicht tun.
Mein Freund hat mir 2 Möglichkeiten zur Lösung dieses Problems empfohlen:
- Über das Idiom "type erasure".
- Durch Signale und Slots
Sie wissen bereits sicher über Signale und Slots Bescheid, und deshalb werde ich über eine Methode sprechen. Knapp.
Das Typ-Löschen-Idiom ermöglicht es Ihnen, den Typ eines beliebigen Objekts zu löschen, indem Sie ihn dahinter verstecken
Gegenstand eines allgemeineren Typs.
Hallo Vorlagen
So sieht es in Worten aus:
- Wir erstellen eine abstrakte Basisklasse A, darin deklarieren wir die virtuelle Funktion SetText
Wir erben von dieser Klasse die bereits vorhandene Template-Klasse B, und sie hat nur:
Feld in Form eines Zeigers auf einen Vorlagentyp
Implementierung der virtuellen Methode SetText
In der Client-Klasse deklarieren wir einen Zeiger vom Typ A
- Verwenden :)
So sieht es in der Praxis aus:
- Eine abstrakte Basisklasse und ihr Nachfolger:
namespace om_animation { class AbstractWritableWidget { public: ~AbstractWritableWidget() {} virtual void SetText(const QString& text) = 0; }; template <class Widget> class WritableWidget : public AbstractWritableWidget { public: WritableWidget(Widget* writable_widget) : writable_widget_(writable_widget) {} ~WritableWidget() {} void SetText(const QString& text) override { writable_widget_->setText(text); } private: Widget* writable_widget_ = nullptr; }; }
- Wir verwenden (nur ein Beispiel):
class Client { public: template <typename T> void Run(T * type){ // do what you want writable_widget_ = new WritableWidget<T> (type); writable_widget_->SetText("Success"); // do what you want } private: AbstractWritableWidget* writable_widget = nullptr; }
template <typename Widget> void om_animation::TextAnimator::RunAnimation(Widget* widget) { if (WritableMatcher::IsWidgetWritable(widget->metaObject()->className())) { if (writable_widget_) { delete writable_widget_; } writable_widget_ = new WritableWidget<Widget>(widget); timer_->start(animation_delay_); } else { throw std::logic_error( "incompatible type for text animation, add type to " "WritableMatcher class"); } }
In echtem Code habe ich auch eine Klasse mit statischen Methoden erstellt, um zu überprüfen, welche Klasse unterstützt
setText-Methode in der Qt-Bibliothek. Es gibt nur einen Vektor unter der Haube. Nichts kompliziertes.
Durch das Metaobjekt erhalten wir den Namen der Klasse, vergleichen Sie ihn mit dem bereits in der Liste. Ja - ja, nein - nein.
Weiterhin habe ich einfache Überprüfung des Zeigers gemacht, und eigentlich schon benutzt.
Wenn das Objekt nicht gefunden wurde, erhält der Client eine Ausnahme.
Das ist alles. Ich finde diese Redewendung sehr cool.
Vielen Dank für Ihre Aufmerksamkeit.
Идиома достаточно интересная, единственное, код кажется весьма громоздким.
В стандарте С++14 также есть возможность объявлять в качестве аргумента лямбда функции auto аргументы. Которые также шаблонизируются. И если метод не существуют у объекта, то проект не скомпилируется.
Спасибо за отзыв. Очень приятно, что кто-то прочитал и ответил.
Не совсем.
Под наследованием интерфейса понимается вот что