Skip to main content.

DOS INTERNATIONAL

This article, published by a german PC magazine called 'DOS International', was written during a summer C++ course at Saarland University.

DOS International

Initially it was supposed to participate in a contest to write a useful program in just 1024 Bytes. The price was 1024 Deutsch Marks, but unfortunately the application seemed to be too specific in order to be generally useful. However the contribution was later reused in the programmer's corner of the same magazine: 'tips and tricks for programmers'.

Below you can find the german version of the article that was published in 'DOS International' in September 1993.

Vektortemplate

vektor.cpp (Listing 2) kompilieren Sie mit Borland C++ ab Version 3.1. Ein
Vektortemplate nutzen alle begeisterten C++-Anhänger, die
wiederverwendbare Software schreiben. Es kann als Ausgangspunkt einer
benutzerdefinierten, mathematischen Bibliothek dienen und bietet dem
Anwender viele Wege zur Erweiterung, wie zum Beispiel ein Matrixtemplate,
das aus mehreren Vektoren dargestellt wird. Das Ziel der
Vektorrepräsentation durch ein Template ist es, unter Ausnutzung der
Überladungsmöglichkeiten von Operatoren und Funktionen
(operator-overloading, function-overloading) eine Syntax zu gestatten,
wie es in der Mathematik üblich ist. Damit erreichen Sie besser
lesbaren und damit leichter verständlichen Code. Der zweite Vorteil
des Templates ist, daß es dem Anwender überlassen ist, welchen
Datentyp er in der Instanz seines Vektors speichern möchte.
Durch die beiden Konstruktoren und das Default-Argument ergeben sich drei
verschiedene Arten der Definition eines Vektorobjektes vom Typ v.

Die erste Definition erzeugt einen dreidimensionalen Vektor v1 mit
Komponenten vom Typ float.

v<float> v2 = v1;

Die zweite Definition erzeugt ein komplettes Duplikat des Vektors v1
mit eigenem Komponentenspeicher.

v<float> v3(4);

Die dritte Definition erzeugt den vierdimensionalen Vektor v3 unter
expliziter Angabe der Dimension.Die Elementfunktion 4 liefert als
Rückgabewert die Dimension eines Vektors:

cout<<v1.d()<<"-dimensional"; //Ausgabe:3-dimensional

Durch das Überladen des Subskriptoperators [] kann der
Anwender explizit auf die einzelnen Komponenten eines Vektors
zugreifen:

cout << v1[1]; //Ausgabe:0,weil erste Komponente hier noch
nicht initialisiert ist.

Die Subskriptfunktion liefert als Rückgabe eine Referenz auf
die spezifizierte Komponente. Dadurch sind Sie in der Lage, mit
dem Subskriptoperator eine Initialisierung des Vektors
durchzuführen.

v1[1]=2.0;
v1[2]=3.5;
v1[3]=1.7;
v2[1]=5.7;
v2[2]=9.1;
v2[3]=4.8;

Mit der Nummerierung hält sich die Operatorfunktion an die
mathematische Notation. Der Anwender spricht bei einem
dreidimensionalen Vektor die Komponenten mit den Indizes 1 bis 3 an.
Template-intern wird zwangsläufig auf die normale C++-Indizierung
von 0 bis 2 umgerechnet. Das Überladen des C++-Ausgabeoperators
<< erlaubt die Ausgabe beliebig-dimensionaler Vektoren innerhalb
der gewohnten Ausgabesequenzen;

cout << "v1=" << v1 << '\n'; // Ausgabe:v1=[2.0,3.5,1.7]

Die arithmetischen Operatoren +, -, * und der Zuweisungsoperator = wurden
überladen, um die einfachen mathematischen Vektoroperationen zu
gestatten: v3=v1;. Der Zuweisungsoperator kopiert die Komponenten und die
Dimension von bestehenden Objekten. Im Unterschied zum Copy-Konstruktor
wird kein neues Objekt erzeugt, sondern ein bestehendes überschrieben.
Die auf Vektoren definierte Skalarmultiplikation unterliegt jedoch einigen
Beschränkungen. Der linke Operand muß ein lvalue sein, und es
können nur Elemente gleichen Datentyps miteinander multipliziert
werden oder Elemente, die sich nach den Typumwandlungsregeln von C++ in
den Datentyp der Komponenten verwandeln lassen.

cout << v1*3; //Ausgabe:[6.0,10.5,5.1]

Der Additionsoperator stellt die komponentenweise Addition zweier
Vektoren zur Verfügung.

cout << vl+v2; //Ausgabe:[7.7,12.6,6.5]

Um bei der Vektorsubtraktion nicht den identischen Code des
Additionsoperators zu benutzen, nur mit dem Unterschied eines
einzigen Zeichens, wurde die Subtraktion mit Hilfe der Addition und
Skalarmultiplikation implementiert. Die Anweisung return *this+w*-1;
führt mit jeder Komponente des Übergabeparameters w eine
Multiplikation mit -1 durch und addiert danach die beiden Vektoren.
Der Subtraktionsoperator kann dann beispielsweise so genutzt werden:

cout << vl-v2; //Ausgabe:[-3.7,-5.6,-3.1]

Dieses Beispiel trägt hoffentlich dazu bei, die Stärken
von C++ gegenüber prozeduralen Programmiersprachen zu
verdeutlichen und herauszustellen, wie einfach es ist, wiederverwendbaren
Code zu schreiben. Das Template soll dem Benutzer als Anregung dienen,
sich mit den Stärken von C++ auseinanderzusetzen und nach Erweiterung
der Funktionen soll es sich als nützlich im Zusammenhang mit der
Entwicklung mathematischer Software erweisen.
(Michael Rumpf/et)


1: //Compiler: Borland C++ 3.1
2: #include <iostream.h>
3: template<class T>class v{
4:  int z;
5:  T* a;
6: public:
7:  v(intd=3){a=new T[z=d];}
8:  v(v<T>&);
9:  -v()<delete a;}
10:  int d()(return z;);
11:  T&operator()(int i);
12:  v<T>operator+(v<T>);
13:  v<T>operator*lT);
14:  v<T>operator-(v<T>);
15:  v<T>operator=(v<T>);
16: friend ostream&operator<<
17:  (ostream&os,v<T>w););
18: template<class T>ostream
19:  &operator<< (ostream&os,v<T>w)
20: {os<<" ["; for (int i=1; i<w.z;i++)
21: os<<w[i]<<',';
22: return os<<w [w.z] <<"] ": }
23: template<class T>v<T>::v(v<T>&w)
24: {a=new T[z=w.z];
25: for(int i=0;i<z;ii+) a[i]=w.a[i];}
26: template<
27:   class T>T&v<T>::operatori[](int i)
28:{if(i>=1&&i<=z)return a[i-1];}
29: template<
30:   class T>v<T>v<T>::operator+(v<T>w)
31: {v<T>s(2);
32: if(z==w.z)for(int i=0;
33: i<z;i++)s.a[i]*=(a+i)+w.a[i];
34: return s;}
35: template<
36:   class T>v<T>v<T>::operator*(T s)
37: {v<T>w(z);
38: for(int i=O;i<z;
39: i++)w.a[i]=a[i]*s;return w;}
40: template<
41:   class T>v<T>v<T>::operator-(v<T>w)
42: {return *this+(w*-1),}
43: template<
44:   class T>v<T>v<T>::operator=(v<T>w)
45: {delete a;a=new T[z=w.z];
46: for(int i=0;
47: i<z;i++)a[i]=w.a[i];return *this;)
48: void main()(v<int> vl,v2;
49:vi[1]=4;vi[2]=6;vi[3]=8;
50: v2=vl;cout (r) vl (r) vl + v2;
51: cout (r) '\n'(r) vi*3; }

>vektor.cpp< beweist, was C++-Programmierer besser als
die Kollegen in prozeduralen Programmiersprachen können.
          
TypeArticle for a Computer Magazine
EnvironmentSun Solaris 5, Windows 3.x, Borland C++ 3.1, GCC