Ich bin ein bisschen verwirrt, ob und wann ich typedef in C ++ verwenden soll. Ich denke, es ist ein Spagat zwischen Lesbarkeit und Klarheit.
Hier ist ein Codebeispiel ohne typedefs:
int sum(std::vector<int>::const_iterator first,
std::vector<int>::const_iterator last)
{
static std::map<std::tuple<std::vector<int>::const_iterator,
std::vector<int>::const_iterator>,
int> lookup_table;
std::map<std::tuple<std::vector<int>::const_iterator,
std::vector<int>::const_iterator>, int>::iterator lookup_it =
lookup_table.find(lookup_key);
if (lookup_it != lookup_table.end())
return lookup_it->second;
...
}
Ziemlich hässlich IMO. Deshalb füge ich ein paar typedefs in die Funktion ein, damit sie besser aussieht:
int sum(std::vector<int>::const_iterator first,
std::vector<int>::const_iterator last)
{
typedef std::tuple<std::vector<int>::const_iterator,
std::vector<int>::const_iterator> Lookup_key;
typedef std::map<Lookup_key, int> Lookup_table;
static Lookup_table lookup_table;
Lookup_table::iterator lookup_it = lookup_table.find(lookup_key);
if (lookup_it != lookup_table.end())
return lookup_it->second;
...
}
Der Code ist immer noch etwas ungeschickt, aber ich werde das meiste Albtraummaterial los. Aber es gibt immer noch die int-Vektor-Iteratoren, diese Variante beseitigt diese:
typedef std::vector<int>::const_iterator Input_iterator;
int sum(Input_iterator first, Input_iterator last)
{
typedef std::tuple<Input_iterator, Input_iterator> Lookup_key;
typedef std::map<Lookup_key, int> Lookup_table;
static Lookup_table lookup_table;
Lookup_table::iterator lookup_it = lookup_table.find(lookup_key);
if (lookup_it != lookup_table.end())
return lookup_it->second;
...
}
Das sieht sauber aus, ist es aber noch lesbar?
Wann sollte ich ein typedef verwenden? Sobald ich einen Albtraumtyp habe? Sobald es mehr als einmal auftritt? Wo soll ich sie hinstellen? Soll ich sie in Funktionssignaturen verwenden oder bei der Implementierung belassen?
c++
coding-style
futlib
quelle
quelle
typedef Input_iterator std::vector<int>::const_iterator;
ist rückwärts#define
gut genug ist.Antworten:
Ihr letztes Beispiel ist sehr gut lesbar, hängt jedoch davon ab, wo Sie die typedef definieren. Typedefs für den lokalen Bereich (wie in Ihrem zweiten Beispiel) sind IMVHO fast immer ein Gewinn.
Ihr drittes Beispiel gefällt mir immer noch am besten, aber vielleicht möchten Sie über die Benennung nachdenken und den Iteratoren Namen geben, die die Absicht des Containers angeben.
Eine andere Möglichkeit wäre, eine Vorlage aus Ihrer Funktion zu machen, damit sie auch mit anderen Containern funktioniert. Nach dem Vorbild von
Das ist auch sehr im Geiste der STL.
quelle
Stellen Sie sich eine
typedef
als Variablendeklaration äquivalent zu einer Funktion vor: Sie ist da, damit Sie ...Persönlich glasiere ich über, wenn ich lange Typnamen gerne
std::vector<int>::const_iterator
mehrmals lesen muss.Ihr drittes Beispiel wiederholt sich nicht unnötig und ist am einfachsten zu lesen.
quelle
typedef
Deklarationen dienen im Wesentlichen dem gleichen Zweck wie die Verkapselung. Aus diesem Grund passen sie nach den gleichen Namenskonventionen wie Ihre Klassen fast immer am besten in eine Header-Datei, weil:typedef
, werden wahrscheinlich auch die Anrufer es tun, insbesondere wie in Ihrem Beispiel, in dem es in den Argumenten verwendet wird.Abgesehen davon wäre Ihr Memo-Code viel sauberer, wenn Sie ihn weiter abstrahieren würden, wie zum Beispiel:
quelle