Und ggf. gibt es hier noch einen weiteren Textabschnitt, der im mobilen Bereich aber nicht zu sehen ist.
Kurz vor dem Feiertag ein weitere Post. Wie bereits angekündigt, möchte ich einfach weitere Steuerelemente zur Ausgabe verwenden, zum anderen ist bisher immer noch das manuelle Aufräumen notwendig. In dem Post RAII - Mauszeiger für VCL + FMX habe ich ja erklärt, dass dieses dank RAII nicht notwendig ist, und durch C++ selber verhindert werden kann. Also möchte ich in diesem Post beginnen, einen entsprechenden RAII- Wrapper entwerfen. Weitere Steuerelemente werde ich im nächsten Post betrachten.
Bei unserem RAII- Wrapper soll über die Spezialisierung einer template- Methode Activate() das Erzeugen der konkreten Hilfsklassen und die Zuordnung übernommen werden, und die notwendige temporäre Variable als privates Element gespeichert werden. Dieses wird benutzt, um beim Verlassen des Gültigkeitsbereich der bisherige Zustand wiederhergestellt werden.
Daraus ergibt sich folgende Klasse.
class TMyStreamWrapper {
private:
std::ostream& str;
std::streambuf* old;
public:
TMyStreamWrapper(std::ostream& ref) : str(ref) { old = 0; }
~TMyStreamWrapper(void) {
if(old != 0) delete str.rdbuf(old);
}
void Reset(void) {
if(old != 0) {
delete str.rdbuf(old);
old = 0;
}
}
template <typename ty> void Activate(ty* element);
operator std::ostream& (void) { return str; };
private: // pre C++11
TMyStreamWrapper(TMyStreamWrapper const& ref) : str(ref.str) { };
void Check(void) { if(old != 0) throw std::runtime_error("Attention, prior activation"); }
};
template<>
inline void TMyStreamWrapper::Activate<std::streambuf>(std::streambuf* buff) {
Check();
old = str.rdbuf(buff);
}
#if defined BUILD_WITH_VCL || defined BUILD_WITH_FMX
template<>
inline void TMyStreamWrapper::Activate<TMemo>(TMemo* element) {
Check();
old = str.rdbuf(new MyMemoStreamBuf(element));
}
#endif
template<typename ty>
inline void TMyStreamWrapper::Activate(ty* element) {
throw std::runtime_error("no specification for TMyStreamWrapper::Activate");
return;
}
Schauen wir uns die Klasse "TMyStreamWrapper" genauer an. Wir definieren zwei Datenelemente. Das erste ist eine Referenz auf einen ostream "str", damit auch auf jede davon abgeleitete Klasse, und repräsentiert den umzulenkenden Stream. Als zweites definieren wir einen Zeiger "old" auf das vorherige streambuf- Element des Streams, das zwischengespeichert wird. Im Konstruktor übergeben wir eine Referenz auf einen ostream als Parameter. Dieser soll neu zugeordnet werden. Da es sich um eine Referenz handelt, muss die Zuweisung zu dem Datenelement "str" in der Kostruktorenliste erfolgen, also vor der öffnenden geschweiften Klammer des Funktionsblocks. Das zweite Datenelement "old" wird mit 0 initialisiert. Ich habe mich hier zur Kompatibilität mit C++98 entschieden, sollten Sie nur einen aktuellen Compiler verwenden, kann und sollte dieses natürlich nullptr sein. Oder sie verwenden die bedingte Compilierung um zwischen der Zuweisung von 0 und nullptr zu unterscheiden.
Im Destruktor wird das bisherige, zwischengespeicherte Datenelement "old" genutzt, um den vorherigen Zustand wiederherzustellen. Dazu wird geprüft, ob das Datenelement ungleich 0 ist,
und dann wird der vorherige Zustand durch den Aufruf von rdbuf() wiederhergestellt und das übergebene Datenelement gelöscht.
Die Methode Reset() setzt den bisherigen Zustand zurück und löscht das vorher übergebene streambuf- Objekt. Dadurch ist es möglich, eine neue Zuordnung vorzunehmen.
Das template Activate() übernimmt diese Zuordnung und bildet den eigentlich wichtigsten Teil damit. Es gibt später die Spezialisierungen, die als explizite inline Methoden unterhalb der Klasse implementiert sind. Spezialisierungen erweitern das Konzept der templates erheblich und verschaffen uns viele neue Möglichkeiten. Aber es ist erstaunlich, das viele diese nicht nutzen.
Wichtig ist dabei die Methode, die einen Zeiger auf ein streambuf- Objekt übernimmt, und damit jedes beliebige von streambuf abgeleitete Objekte übernehmen kann. Es ist ein universeller Zugang zu diesem Wrapper. Den Abschluss bildet die allgemeine template Definition (ohne Spezialisierung), die aber einen Laufzeitfehler auslöst. Zwischen diesen beiden kann später alles ergänzt werden, im obigen Listing ist es die von uns schon durchgeführte Umlenkung auf ein Memofeld mit Hilfe der Klasse MyMemoStreamBuf aus dem Post Verwendung von Standardstreams zur Ausgabe in Memofeldern.
Der Funktionsoperator wird genutzt, um den umgeleiteten Stream von außen auch benutzen zu können. Deshalb wird hier einfach eine Referenz auf ostream zurückgeliefert, mit dem Datenelement "str".
Die Check- Methode wird genutzt, um bei der Aktivierung eine mehrfache Zuweisung zu verhindern. Sollte das Datenelement "old" ungleich 0 sein, wird hier ein Laufzeitfehler ausgelöst.
Als letztes der Kopierkonstrukor. Mit C++11 könnte ich diesen einfach löschen, weil ich hier aber kompatible zu älteren Compilern bleiben wollte, habe ich mich für den bekannten Trick entschieden, zu verhindern das von außen eine Kopie der Instanz initiiert wird. Deshalb wird der Kopierkonstruktor einfach in den privaten Teil verschoben, so dass nur noch die Methoden der Klasse selber Kopien erzeugen könnten. Wieder gilt hier, sollten sie nur einen aktuellen Compiler verwenden, löschen sie den Kopierkonstruktor bitte.
Nun können wir diesen Wrapper verwenden, um die Zuordnung am Programmende rückgängig zu machen und sicherzustellen, dass es zu keinen Fehlern kommt.
Keine Kommentare
Dieses Seminar richtet sich primär an Einsteiger, die über Programmierkenntnisse, vorzugsweise in C++ verfügen und auf den C++Builder wechseln wollen. Es ist aber auch für Umsteiger von einer wesentlich älteren Version geeignet.
3 Tage
8 Teilnehmer
Dieses Seminar richtet sich an alle Entwickler, die ihre bestehenden Anwendungen vom klassischen C++- Compiler zum neuen, auf Clang basierenden Compiler im C++- Builder umstellen wollen.
3 Tage
8 Teilnehmer
In diesem Seminar erhalten Sie eine kompakte Einführung in die jeweils aktuelle Version des C++Builder (aktuell 10.3.3). Der C++Builder ist ein plattformübergreifendes Entwicklungstool, mit der Sie performante, native Anwendungen für die Zielplattformen Windows (32bit, 64bit), Mac OS (32bit), iOS und Android entwickeln kann.
5 Tage
8 Teilnehmer
Wie der Titel der Schulung sagt, geht es hier um die Entwicklung von nativen Anwendungen für mobile Endgeräte (App) mit dem C++Builder (aktuell 10.3.3).
2 Tage
8 Teilnehmer
Dieser Kurs richtet sich an C++ Entwickler, die den C++Builder nutzen und ihre Kenntnisse vertiefen wollen. Dabei geht es neben der Verwendung der Komponenten und den Eigenschaften der Sprache C++, besonders auch darum, beides vernünftig zu verbinden.
3 Tage
8 Teilnehmer
Dieses Seminar richtet sich an C++ Programmierer, die den Zugriff auf Datenbanken in ihren Anwendungen erweitern wollen. In diesem Seminar werden die wichtigsten Komponenten des C++ Builders für Datenbankzugriff erläutert, aber es wird auch gezeigt, wie sie diese in eine saubere Anwendungsarchitektur integrieren können.
3 Tage
8 Teilnehmer
Dieses Seminar richtet sich an C++ Programmierer, die Erfahrungen mit dem den Datenbankkomponenten des C++ Builders gesammelt haben, und nun skalierbare Datenbankanwendungen entwickeln wollen. In diesem Seminar wird die Bedeutung von ANSI C++ - Schnittstellen zwischen der Businesslogik einer Anwendung und der Datenbank gezeigt.
3 Tage
6 Teilnehmer
Dieser Kurs richtet sich an Softwareentwickler, die die Elemente der Programmiersprache C als Basis für einen späteren Einstieg in die objektorientierte Programmierung mit C++ lernen wollen.
3 Tage
8 Teilnehmer
Dieses Seminar richtigt sich an die Programmierer, die von C nach C++ umsteigen wollen. Es werden die wichtigsten Erweiterungen der Sprache C++, und die Unterschiede zu C ausführlich besprochen.
3 Tage
5 Teilnehmer
Dieses Seminar richtigt sich an die Programmierer, die von C nach C++ umsteigen wollen. Es werden die wichtigsten Erweiterungen der Sprache C++, und die Unterschiede zu C ausführlich besprochen.
5 Tage
8 Teilnehmer
Wir wurden oft gefragt, ob wir eine Schulung "mit allem" machen könnten. Ein größeres Beispiel, beginnend mit einer Idee, daraus eine Architektur entwickeln, und dann unabhängig in C++ implementieren. Die Erweiterungen nur verwenden, ohne das diese unsere Struktur und Architektur bestimmen.Und wenn es geht, auch noch mit Entwicklung eines Zugriffs für mobile Anwendungen verbinden.
5 Tage
8 Teilnehmer
In diesem Seminar lernen Sie, welche Open Source- Tools Sie für Ihre tägliche Arbeit mit dem aktuellen C++ Builder 10.3.2 nutzen können. Dabei geht es um Lösungen zu den Themen Dokumentieren, Metriken, Codeanalyse und Codeverwaltung.
2 Tage
6 Teilnehmer