Du bist nicht angemeldet.

Stilllegung des Forums
Das Forum wurde am 05.06.2023 nach über 20 Jahren stillgelegt (weitere Informationen und ein kleiner Rückblick).
Registrierungen, Anmeldungen und Postings sind nicht mehr möglich. Öffentliche Inhalte sind weiterhin zugänglich.
Das Team von spieleprogrammierer.de bedankt sich bei der Community für die vielen schönen Jahre.
Wenn du eine deutschsprachige Spieleentwickler-Community suchst, schau doch mal im Discord und auf ZFX vorbei!

Werbeanzeige

Pixma

Frischling

  • »Pixma« ist der Autor dieses Themas

Beiträge: 35

Wohnort: Mainz

Beruf: Fachinformatiker für Anwendungsentwicklung

  • Private Nachricht senden

1

27.12.2014, 14:01

eigene U16 String Klasse

Hallo,

ich habe zurzeit ein kleines Problem. Ich habe eine eigene String Klasse entwickelt mit welcher ich wchar_t speichern möchte, zurzeit verwende ich zum debuggen noch char.
Nun tritt zwar kein Compilerfehler auf, jedoch habe ich die Adresse des Strings aus der Hashtabelle noch einmal in einer Variable gespeichert zum debuggen.
Wenn ich nun in die Watchlist "test1" eintrage, dann bekomme ich die Werte angezeigt, jedoch zeigt Visual Studio mir, dass mBaseString leer sei (size=0).
Dem ist aber nicht so. Dem string habe ich "Hallo Welt" zugewiesen.

U16String.h

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include "WrappedList.h"
#include "WrappedMap.h"
#include <iostream>
//#include <map>

class  U16String
{
private:
    WrappedList<char> *mBaseString;
    static WrappedMap<unsigned int, WrappedList<char>> mBaseTable;
    //static std::map<unsigned int, WrappedList<char>> mBaseTable;
    int mBaseId = 0;

public:
    U16String(const char* text);
};


WrappedList.h

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
#include <list>

template<typename T>
class WrappedList
{
public:
    void add(T item);

    unsigned int count();

private:

    std::list<T> mList;
    unsigned int mCount = 0;
};


template<class T>
void WrappedList<T>::add(T item)
{
    mList.push_back(item);
    mCount++;
}

template <class T>
unsigned int WrappedList<T>::count()
{
    return mCount;
}


WrappedMap.h

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
#include <map>

template<class TKey, class TValue>
class WrappedMap
{
public:
    void add(TKey key, TValue);
    bool containsKey(TKey key);
    TValue at(TKey key);


private:
    std::map<TKey, TValue> mMap;
};


template<class TKey, class TValue>
void WrappedMap<TKey, TValue>::add(TKey key, TValue value)
{
    this->mMap.insert(std::pair<TKey, TValue>(key, value));
}

template<class TKey, class TValue>
bool WrappedMap<TKey, TValue>::containsKey(TKey key)
{
    bool containsKey = false;

    std::map<TKey, TValue>::iterator it;
    for (it = mMap.begin(); it != mMap.end(); ++it)
    {
        if (it->first == key)
        {
            containsKey = true;
            break;
        }
    }
    return containsKey;
}

template<class TKey, class TValue>
TValue WrappedMap<TKey, TValue>::at(TKey key)
{
    TValue value;
    std::map<TKey, TValue>::iterator it;
    for (it = mMap.begin(); it != mMap.end(); ++it)
    {
        if (it->first == key)
        {
            value = it->second;
            break;
        }
    }
    return value;
}

U16String.cpp

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#include "U16String.h"

using namespace std;

// WARNING
// DO NOT CHANGE mBaseString
// ADD NEW STRING ON mBasteTable and give the address to mBaseString
// WARNING
WrappedMap<unsigned int, WrappedList<char>> U16String::mBaseTable;
//std::map<unsigned int, WrappedList<char>> U16String::mBaseTable;
U16String::U16String(const char* text)
{
    WrappedList<char> tempBaseString;
    for (unsigned int i = 0; i < strlen(text); i++)
    {
        tempBaseString.add(text[i]);
    }
    mBaseId = unsigned int(text);
    bool isInTable = mBaseTable.containsKey(mBaseId);
    if (!isInTable)
    {
        mBaseTable.add(mBaseId, tempBaseString);
    }
    mBaseString = &mBaseTable.at(mBaseId);
}


main.cpp

C-/C++-Quelltext

1
2
3
4
5
6
#include "U16String.h"

int main()
{
    U16String test1 = "Hallo Welt";
}


Des weiteren möchte ich nochmal wissen, ob es wirklich eine gute Idee ist STL Container zu wrappen wie ich das gemacht habe.
Mir gings bei dem Gedanken darum, dass man diese zum Beispiel in der Zukunft auswechseln könnte durch andere custom Container.
Auch über Kritik wäre ich sehr dankbar.

Mit freundlichen Grüßen


Dennis

Legend

Alter Hase

Beiträge: 731

Beruf: Softwareentwickler

  • Private Nachricht senden

2

27.12.2014, 14:17

Also deine WrappedList ist wohl sicher keine gute Idee. Die Anzahl an Elementen kann dir auch eine std::list direkt verraten. Ggf. passt dir ein std::vector hier aber auch gleich besser ins Konzept.

Und zu deiner WrappedMap ist zu sagen, dass du dir http://www.cplusplus.com/reference/map/map/find/ ansehen solltest.

Sorry, das klingt vielleicht nicht nett, aber ich denke du solltest eher versuchen die STL Container besser zu nutzen, anstatt deine Wrapper drum rum zu bauen. Was die Auswechselbarkeit angeht, bin ich aber selber am überlegen ob man das mit der STL in dem selben Stile wie z.B. in C# hinbekommen könnte. Ich sehe da aber auch nicht wirklich, wie deine Wrapper da helfen sollen.
"Wir müssen uns auf unsere Kernkompetenzen konzentrieren!" - "Juhu, wir machen eine Farm auf!"

Netzwerkbibliothek von mir, C#, LGPL: https://sourceforge.net/projects/statetransmitt/

NachoMan

Community-Fossil

Beiträge: 3 885

Wohnort: Berlin

Beruf: (Nachhilfe)Lehrer (Mathematik, C++, Java, C#)

  • Private Nachricht senden

3

27.12.2014, 14:51

Deine at-Methode in der WrappedMap Klasse macht den größten Vorteil dieses Containers zunichte. Eine Map ist sortiert. Das bedeutet, dass Suchvorgänge bei vielen Elementen stark optimiert werden können. Stell dir vor du hättest eine lange Reihe von zufälligen Zahlen und sollst eine heraussuchen. Wenn die Reihe nicht sortiert ist wirst du eine Ewigkeit brauchen. Wenn sie aber sortiert ist findest du die Zahl in wenigen Sekunden.
Allerdings macht das für einen Computer erst bei ein paar tausend Elementen und häufigen Suchvorgängen Sinn.
"Der erste Trunk aus dem Becher der Erkenntnis macht einem zum Atheist, doch auf dem Grund des Bechers wartet Gott." - Werner Heisenberg
Biete Privatunterricht in Berlin und Online.
Kommt jemand mit Nach oMan?

Pixma

Frischling

  • »Pixma« ist der Autor dieses Themas

Beiträge: 35

Wohnort: Mainz

Beruf: Fachinformatiker für Anwendungsentwicklung

  • Private Nachricht senden

4

27.12.2014, 16:09

hi,
schonmal vielen Dank für eure Kritik.
@ Legend danke für deine Konstruktive Kritik.
Mir wurde nur nicht ganz klar ob du generell gegen eine Wrapper Klasse bezüglich der Map und List bist oder du aussagen möchtest, dass ich die Wrapper Klasse in Form von der STL aufbauen soll. Sodass man wieder normal mit Iteratoren zugreift.
Ich danke dir aufjedenfall schonmal, mir ist halt wichtig das diese Unabhängig sind, sodass ich später mal wie gesagt zum Beispiel meine eigene List Klasse machen kann. Es ist zwar nicht geplant eine eigene Klasse zu schreiben, weil die STL ist ja an sich sehr gut denke ich, aber ich weiß halt nicht was in der Zukunft kommt.

@ NachoMan
Danke auch dir für die konstruktive Kritik.
hmm mir ist performance schon wichtig, bin zurzeit am überlegen ob ich bei der Wrapper Klasse bleibe oder ob ich die STL Klassen ohne Wrapper benutze. Bin mir jedoch nicht sicher, begründung habe ich im Teil bezüglich @Legend geschrieben.

Schonmal vielen Dank :)

5

27.12.2014, 16:52

Nutz die STL so wie sie ist, das ist performanter und einfacher.

Beiträge: 1 223

Wohnort: Deutschland Bayern

Beruf: Schüler

  • Private Nachricht senden

6

27.12.2014, 16:55

Zitat von »Legend«

Was die Auswechselbarkeit angeht, bin ich aber selber am überlegen ob man das mit der STL in dem selben Stile wie z.B. in C# hinbekommen könnte.

Auswechselbarkeit ist in C++ eigentlich sehr gut.
Alle STL Container besitzen bereits soweit möglich das gleiche Interface.

Die Frage ist aber auch, wozu eigentlich?
In eigentlich wirklich fast allen Fällen ist ein "std::vector" doch eh das Beste wegen praktischem Random Access und außerdem noch effizienter.
Dann gibt es noch die assoziativen Containern die noch ihren Anwendungsbereich haben können, aber die beiden Gruppen gegeneinander austauschen zu können, scheint mir nicht sinnvoll.

Zitat von »Legend«

Ich danke dir aufjedenfall schonmal, mir ist halt wichtig das diese Unabhängig sind, sodass ich später mal wie gesagt zum Beispiel meine eigene List Klasse machen kann.

Verwende einen "std::vector". ;) Warum willst du ihn eigentlich selber schreiben? Eigentlich gibt es keinen sinnvollen Grund dazu.
Wenn es dich glücklich macht, kannst du auch einfach einen Type alias auf den zugrunde liegenden STL- Typen machen, dann könnte man im hypothetischen Fall jederzeit auf die eigene Implementierung wechseln.

Einen Wrapper dafür zu schreiben ist eine einzige riesige Zeitverschwendung. Die Zeit könntest du später zum Beispiel besser in sinnvollere Performanceoptimierungen stecken.

Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von »Spiele Programmierer« (27.12.2014, 18:16)


Schorsch

Supermoderator

Beiträge: 5 145

Wohnort: Wickede

Beruf: Softwareentwickler

  • Private Nachricht senden

7

27.12.2014, 18:36

Warum überhaupt List oder Vector. Ein String ist ja eigentlich nicht mutable. Das heißt bei der Erzeugung ist seine Größe bekannt. Warum also nicht einfach einen Smartpointer als Array nehmen?
„Es ist doch so. Zwei und zwei macht irgendwas, und vier und vier macht irgendwas. Leider nicht dasselbe, dann wär's leicht.
Das ist aber auch schon höhere Mathematik.“

Legend

Alter Hase

Beiträge: 731

Beruf: Softwareentwickler

  • Private Nachricht senden

8

27.12.2014, 19:49

@Pixma: Ich bin selbst kein Fan der STL. Ihre Syntax finde ich eigentlich recht hässlich und manchmal überrascht mich wie manche Methoden benannt sind. Ich finde da die entsprechenden Klassen in C#, Java und in älteren Qt-Versionen erheblich angenehmer. Deswegen bin ich dem auch nicht ganz abgeneigt, dass man sich ab und an doch mal weitere Methoden an den STL Objekten wünscht.

Trotzdem: Ich würde eher überlegen von den STL Klassen zu erben, anstatt einen Wrapper zu bauen. Auf diese Weise müsste ich nicht jede einzelne Methode wrappen. Stattdessen könnte ich Methoden, die ich vermisse, zusätzlich implementieren. Probleme erwarte ich eigentlich keine, aber wissen tu ich das jetzt nicht.

@Spieleprogrammierer: Das ein vector heutzutage oft das performanteste Mittel ist, dem stimme ich zu. Aber speziell bei den assoziativen Containern kann man eine derartige Aussage wohl nicht so leicht treffen.

Gute Austauchbarkeit sehe ich z.B. bei C# gegeben. Dort reicht man im Idealfall eh nur IEnumerable<>-Objekte weiter, hinter denen sich eine List oder auch eine Values-Collection eines Dictionaries befinden könnte (oder auch ganz anderes ...). Bei mir auf der Arbeit gab es schon öfters Fälle wo man mit einer List angefangen hat und Objekte in der Liste nach einem Kriterium sucht. Dann stellt man fest, das dauert zu lange, also macht man ein Dictionary<Kriterium, Objekt> draus und erhält einen sehr schnellen Zugriff Anhand des Kriteriums. Eine andere Methode die nur ein IEnumerable<Objekt> als Parameter braucht, muss man nun nicht weiter anzupassen. Der übergibt man jetzt nur die ValuesCollection statt der List und gut ist.
Bei der STL sehe ich dagegen keine Möglichkeit als alle Methoden anzupassen. Machbar, aber natürlich ein Aufwand.

@Schorsch: Also laut diesem Link hier (http://www.cprogramming.com/tutorial/string.html) sind std::string Objekte mutable.
"Wir müssen uns auf unsere Kernkompetenzen konzentrieren!" - "Juhu, wir machen eine Farm auf!"

Netzwerkbibliothek von mir, C#, LGPL: https://sourceforge.net/projects/statetransmitt/

9

27.12.2014, 20:03

Trotzdem: Ich würde eher überlegen von den STL Klassen zu erben, anstatt einen Wrapper zu bauen. Auf diese Weise müsste ich nicht jede einzelne Methode wrappen. Stattdessen könnte ich Methoden, die ich vermisse, zusätzlich implementieren. Probleme erwarte ich eigentlich keine, aber wissen tu ich das jetzt nicht.

STL Klassen besitzen keinen virtuellen Destruktor. Von ihnen (public) zu erben ist also eine ganz schlechte Idee (Slicing, delete).
"Theory is when you know something, but it doesn’t work. Practice is when something works, but you don’t know why. Programmers combine theory and practice: Nothing works and they don’t know why." - Anon

Legend

Alter Hase

Beiträge: 731

Beruf: Softwareentwickler

  • Private Nachricht senden

10

27.12.2014, 20:05

Der Teufel steckt wie immer im Detail.
"Wir müssen uns auf unsere Kernkompetenzen konzentrieren!" - "Juhu, wir machen eine Farm auf!"

Netzwerkbibliothek von mir, C#, LGPL: https://sourceforge.net/projects/statetransmitt/

Werbeanzeige