Veröffentlicht: Dezember 2009
Von Richard Kaiser und Alexander Kaiser
Eine Header-Datei, die außerhalb der Formularklasse in eine Windows Forms-Anwendung aufgenommen wird, kann im Wesentlichen alle Anweisungen von Standard-C und C++ enthalten. Auf diese Weise können auch viele bestehende C/C++-Programme mit wenig Aufwand auf .NET portiert werden. Insbesondere ist es nicht notwendig, solche Programme nach C# umzuschreiben, um sie auf .NET zu portieren.
Die folgenden Beispiele sollen einfach nur zeigen, wie das Schema aus dem letzten Abschnitt mit einfachen C/C++-Anweisungen und nicht ganz so einfachen Elementen der C++-Standardbibliothek oder der Boost-Bibliothek verwendet werden kann. Es ist nicht beabsichtigt, diese Sprachelemente zu erklären.
Dieser Artikel ist ein kurzer Auszug aus dem Buch „C++ mit Microsoft Visual C++ 2008“ (ISBN 978-3540238690), das C++ mitsamt den Visual C++-Erweiterungen (C++/CLI) umfassend darstellt. Der Verfasser dieses Buches ist ein erfahrener C++- und C#-Trainer, der auch für Firmenschulungen zur Verfügung steht.
Die folgenden Anweisungen sind ein inhaltlich sinnloses Sammelsurium typischer C/C++ Sprachelemente, die einfach nur zeigen sollen, dass eine Windows Forms-Anwendung solche Sprachelemente enthalten kann:
C++
const int Max=17; // eine globale Variable eines vordefinierten Typs
class Punkt { // eine Klasse
double x,y;
public:
Punkt(double x_, double y_):x(x_),y(y_){}
};
const char* Msg="Hallo Welt"; // ein nullterminierter String
#include <string.h> // eine
C-Bibliothek
using namespace
System::Windows::Forms;
using namespace System;
void f(TextBox^ tb, int n) // eine Funktion
{ // inhaltlich völliger Unsinn
int a[Max]; // ein Array
for (int i=0; i<Max; i++) //
eine Kontrollstruktur
a[i]=i*i;
int* p=new int; // ein Zeiger
*p=n*strlen(Msg);
for (int i=0; i<Max; i++)
if
(i%10==0)
tb->AppendText(String::Format("a[{0}]={1}\r\n",i,a[i]));
}
Will man den Wert der Funktion f mit einem in einer TextBox eingegebenen Parameter anzeigen, kann man eine ButtonClick-Funktion verwenden wie
C++
private: System::Void
button1_Click(System::Object^ sender,
System::EventArgs^ e)
{
int
n=Convert::ToInt32(textBox1->Text);
f(textBox1, n);
}
Wenn in diesen Beispielen nullterminierte Strings und zugehörige Funktionen wie
C++
const char* Msg="Hallo Welt"; // ein nullterminierter String
char a[11];
strcpy(a,Msg);
verwendet werden, soll damit nur gezeigt werden, dass das
möglich ist. Es soll aber nicht bedeuten, dass Sie solche Datentypen und
Anweisungen verwenden sollen. Der
Compiler weist durch eine Warnung wie
warning C4996: 'strcpy': This function or variable may be
unsafe.
Consider using strcpy_s instead.
darauf hin, dass nullterminierte Strings und die zugehörigen Funktionen unsicher sein können. Allerdings ist der Hinweis, stattdessen „secure library functions“ wie strcpy_s zu verwenden, meist nur für C-Programme die richtige Alternative. In C++ besteht normalerweise keine Veranlassung, Strings mit char* darzustellen, da Stringklassen wie string oder String zur Verfügung stehen. Diese sind einfacher und mindestens genauso sicher wie die „secure library functions“.
Eine Header-Datei, die außerhalb der Formularklasse in eine Windows Forms-Anwendung aufgenommen wird, kann auch die Klassen der C++-Standardbibliothek verwenden. Auf diese Weise steht die Standard Template Library (STL) mit ihren Stringklassen, Container-Klassen (z.B. vector) und Streamklassen in Windows Forms-Anwendungen zur Verfügung.
Die folgenden Ausführungen sollen das an einigen einfachen Beispielen zeigen.
Die Klasse string der C++-Standardbibliothek kann nach
C++
#include <string>
using
std::string; // oder: using namespace std;
verwendet werden:
C++
string s1="Hallo Welt";
Diese Klasse hat gegenüber nullterminierten Strings viele Vorteile. Mit ihren Elementfunktionen kann man Strings bearbeiten oder nach Zeichenfolgen durchsuchen. Als einfaches Beispiel soll eine Funktion dienen, die an einen String die Zeichen „.txt“ anhängt, falls dieser nicht schon mit diesen Zeichen endet:
C++
string appendTxtExtension(string fn)
{
if
(fn.find(".txt")!=fn.length()-4)
return fn+".txt";
else return fn;
}
Die Containerklassen der Standardbibliothek haben den Vorteil, dass sie ihren Speicher automatisch verwalten. Falls ein neues Element in einem Container abgelegt wird und der bisher reservierte Speicherplatz nicht ausreicht, wird automatisch neuer Speicher reserviert. Als einfaches Beispiel soll ein vector dienen. Diese Containerklasse steht nach
C++
#include <vector>
using
std::vector; // oder: using namespace std;
zur Verfügung. Mit
C++
vector<int> v;
erhält man einen vector
v, der int-Werte speichern kann. Neue
Elemente kann man einem vector mit
der Elementfunktion push_back
hinzufügen. Diese Elemente kann man wie Elemente eines Arrays mit dem Indexoperator ansprechen:
C++
void useVector(TextBox^ textBox1,
int n)
{
vector<int> v;
for (int i=1; i<=n; i++) //
fügt v 100 Elemente hinzu
v.push_back(i*i);
for (int i=0;
i<v.size();i++)//oder size_t anstatt int
textBox1->AppendText(v[i].ToString()+"\r\n");
}
Mit den fstream-Klassen kann man Dateien anlegen und lesen:
C++
#include <fstream>
using
namespace std;
void useFstream(TextBox^ textBox1, int n)
{
ofstream
fout("c:\\test.dat",ios::binary);
for (int i=0; i<n; i++)
fout.write((char*)&i,sizeof(int));
fout.close();
ifstream
fin("c:\\test.dat",ios::binary);
int i;
while (fin.read((char*)&i, sizeof(int)))
textBox1->AppendText(i.ToString()+"\r\n");
fin.close();
}
Boost ist eine Sammlung von über 50
Bibliotheken, die alle im Quelltext verfügbar sind und frei (d.h. ohne
Gebühren, im Rahmen der Boost Lizenz) verwendet werden können. Sie enthalten
viele Funktionen, Klassen usw., die in vielerlei Anwendungsbereichen nützlich
sein können.
Das Boost Projekt
geht auf eine Initiative von Mitgliedern des C++-Standardisierungskomitees
zurück, die damit unter anderem das Ziel verfolgten, Referenzimplementationen
für zukünftige C++-Erweiterungen zur Verfügung zu stellen und mit diesen
praktische Erfahrun¬gen zu sammeln. Ein wichtiges Entwurfsziel ist
Portabilität. Alle Bibliotheken können mit jedem weitgehend standardkonformen
C++-Compiler unabhängig von der Plattform verwendet werden. Sie gehören zu den
qualitativ hochwertigsten C++-Bibliotheken. Durch ihre große Verbreitung ist
ihr Design und ihre Funktionalität auf einer breiten Basis erprobt.
Die
Boost-Bibliotheken stehen im Quelltext zur Verfügung. Ihre Installation ist
einfach: Nachdem man sie entpackt hat, muss man lediglich unter Projekt|Eigenschaften|Konfigurationseigenschaften|C/C++|Allgemein|Zusätzliche
Includeverzeichnisse das Verzeichnis mit der Boost-Bibliothek (z.B.
c:\Boost\boost_1_41_0) eintragen.
Als Beispiel soll
hier die Berechnung einer CRC-Prüfsumme dienen:
C++
#include <boost/crc.hpp> // for boost::crc_basic,
boost::crc_optimal
#include
<boost/cstdint.hpp> // for
boost::uint16_t
void testCRC()
{
const char* buf="Hello World";
boost::crc_basic<16> crc_ccitt1( 0x1021, 0xFFFF, 0, false, false
);
crc_ccitt1.process_bytes( buf, strlen(buf) );
int x=
crc_ccitt1.checksum() ;
}
Die sogenannten TR1-Erweiterungen sind
die erste große Erweiterung der C++-Standardbibliothek seit der Verabschiedung
des C++-Standards. Der Name kommt von „Technical Report“: Damit bezeichnet die
Standardisierungsorganisation ISO Dokumente, die zwar keine bindenden Standards
sind, aber fast das Gewicht von Standards haben, da sie durch ISO-Gremien
verabschiedet wurden. Ein großer Teil der TR1-Erweiterungen wird auch
Bestandteil des nächsten C++-Standards sein.
Die TR1-Erweiterungen
sind ab der Version 2008 in Visual Studio enthalten und gehören zum
Namensbereich std::tr1. Als Beispiel
soll hier gezeigt werden, wie man die Klasse shared_ptr verwenden kann. Diese Klasse führt eine einfache und
effiziente Form von Garbage collection durch, indem sie den Speicher auf ein
mit new erzeugtes Objekt wieder frei
gibt, wenn kein Verweis mehr darauf existiert.
C++
#include <memory>
using
namespace std::tr1;
void testSharedPtr()
{
shared_ptr<int> s1; // wie int* p1;
shared_ptr<int> s2(new int(17)); // wie
int* p2=new int(18);
} // gibt den Speicher auf das mit new erzeugte Objekt wieder frei
Zurück: Eine Vorlage für Windows Forms-Anwendungen mit Standard-C++| Weiter: Konversionen zwischen string und String