2009-11-11 6 views
6

Ich habe eine kleine Frage: Wie finde ich heraus, welcher Typ ein C++ Zeiger ist?Finden Sie heraus Typ von C++ Void Zeiger

Ich benutze oft eine kleine Funktion in meiner Konsolenprogramme Eingang zu sammeln, die etwa wie folgt aussieht:

void query(string what-to-ask, [insert datatype here] * input) 

Ich möchte eine generische Form erstellen, einen void-Zeiger verwenden, aber ich kann nicht cin einen void pointer, also wie finde ich heraus, dass es sich um einen Typ handelt, damit ich ihn umsetzen kann?

+10

Sie es werfen und Daumen drücken. –

+0

Schauen Sie sich an, wie die native C-Funktion 'scanf()' es handhabt. –

+0

Eine Frage: Soll der Benutzer in der Lage sein, ALLES einzugeben und dann entsprechend zu analysieren? Nehmen wir an, er gibt 14 ein, dann wollen Sie ein "int", oder 15.4 wollen Sie ein float? Das ist es? –

Antwort

14

Es ist eine lange Zeit seit dem letzten Mal, als ich in C++ codiert, aber ...

Können Sie nicht ein Template verwenden?

+2

Das OP sucht nach RTTI, und das gilt nicht für void *. Vorlage ist die Antwort. – Tanktalus

0

Wenn ich verstehe, was Sie fragen, dann ist der übliche Weg, dies zu tun, eine Schnittstellenklasse zu erstellen, die query(string what-to-ask) unterstützt und dann anstelle eines void-Zeigers übergeben Sie einfach einen Zeiger auf die Schnittstelle. Dann können Sie query() für diese Instanz aufrufen.

9

Sie können nicht.

Eine Alternative ist jedoch, void pointers zu entfernen, alles aus einer gemeinsamen Basisklasse abzuleiten und RTTI zu verwenden.

Ein Beispiel:

class Base 
{ 
public: 
    virtual ~Base() {} 
}; 

class Foo : public Base { /* ... */ }; 

void SomeFunction(Base *obj) 
{ 
    Foo *p = dynamic_cast<Foo*>(obj); 
    if (p) 
    { 
     // This is of type Foo, do something with it... 
    } 
} 
+1

sollte 'dynamic_cast ' –

+0

ja, das ist was ich meinte. :-) Fest. – asveikau

+1

Seien Sie sich bewusst, dass dynamic_cast sehr langsam sein kann - leicht eine Mikrosekunde für jede Klassenhierarchie, die größer als trivial ist. – Crashworks

0

Nope. Du kannst das nicht tun. Wenn Sie so etwas brauchen, empfehle ich Boost.Any.

2

void* ist das Formular alle Daten haben. Sie können es nicht "bestimmen" - es ist es, alle Daten, die Sie in Programm haben sindvoid*! Ja, sie sind rohe Stücke der Erinnerung, von Entwurf.

Sie könnte Programm ganzen Code mit der Verwendung von void* nur. Glücklicherweise bietet Ihnen die C-Sprache Bequemlichkeit Ihnen, so dass Sie einige Daten manipulieren können, wie sie nicht void* waren. Aber wenn Sie diese Bequemlichkeit nutzen, sollten Sie sie nicht auf void* werfen und vergessen, welcher Typ sie waren.

+0

Alle POINTERS sind ungültig *. Das letzte Mal, als ich überprüft habe, ist ein Char nicht ungültig *. Ein int ist möglicherweise nicht ungültig *. Ein Float ist nicht ungültig *. Aber char *, int * und float * sind. – luiscubal

+1

Sein Punkt ist, dass alle Daten nichts als Bytes im Speicher sind. Ints, Chars, Strings usw. sind nur Interpretationen. –

2

Ihre Frage ist nicht klar, für mich, aber vielleicht das, was wollen Sie ist query

void query(string what2ask, int* input) { 
    cout << what2ask; 
    cin >> *input; 
} 


void query(string what2ask, float* input) { 
    cout << what2ask; 
    cin >> *input; 
} 

int age; 
float sqrt2; 
query("How old are you?", &age); 
query("What's the square root of 2?", &sqrt2); 
+0

Plus eins für Einfachheit und Klarheit – Brad

0

zu überlasten Wenn Sie den Datentyp selbst steuern, würde ich wahrscheinlich eine Klasse/Struktur machen, die eine ENUM enthält von alle Datentypen, die Ihnen wichtig sind, und übergeben Sie diese. Sie könnten dann den übergebenen Zeiger nach seinem Datentyp abfragen und dann entsprechend umwandeln.

IE (Pseudo-Code Warnung -. Dies nun als struct Behandlung)

class MyDataType { 
    enum aDataType type; 
    void * myData; 
} 

void query(string whatToAsk, MyDataType * pdata) 
{ 
    switch (pdata.type) { 
     case integer: 
       int * workInt = (int *) pdata; 
       do whatever you want to to get the data 
       break; 
     case someFunkyObject: 
       someFunkyObject pob = (SomeFunkyObject *) pdata; 
       Do whatever you want with the data. 

     etc. 
    } 
} 
+1

Wenn ich mit Enums (anstatt mit RTTI) Tagging, wäre ich mehr geneigt zu machen "myData" eine Union statt einer Lücke * ... Weniger Zeiger auf diese Weise, und keine doppelte Indirektion. Obwohl es viel mehr C-Stil als C++ ist. – asveikau

0

Sie es als char * in und dann analysieren die Zeichenfolge (char von char) lesen konnte, um zu bestimmen, ob es ein int, float, string, was auch immer. Der schwierige Teil ist es, es zu konvertieren.

Zum Beispiel: ('' Charakter a)

für jedes Zeichen in Zeichenfolge

wenn

++ decimalcount

else if (Zeichen ein Buchstabe)

++ briefcount

Ende für Schleife

wenn decimalcount> 0 & & lettercount == 0 Parse durch jede Ziffer von rechts nach links, durch Potenzen von 10 Multiplikation und Addition der Summe

else if decimalcount == 1 & & lettercount == 0

lernen, wie man schwimmt in binär dargestellt werden, und jemand andere Funktion zu finden, es zu konvertieren für Sie

else if lettercount> 0

es ist eine Zeichenfolge. Yay!

+0

Dies gilt nur für Zeichenketten. Es wäre natürlich zum Scheitern verurteilt, einen 'void *' oder irgendeinen anderen willkürlichen Zeiger als 'char *' neu zu interpretieren, da natürlich jeder arithmetische Typ zufällig Bytes enthalten kann, die das gleiche Bitmuster wie [einfügen Lieblings-ASCII-Zeichen hier]. Abgesehen von der Datenwiederherstellung/Forensik ist es sinnlos, Ratespiele mit dereferenzierten Zeigern zu spielen. Ich sage nicht, dass Sie es sind, aber das ist eine der Interpretationen der OP-Frage, so dass es die Betonung trägt –

4

Anstatt eine void* umgeben zu müssen, die Sie dann in den richtigen Typ umwandeln müssen, sollten Sie wahrscheinlich eine Vorlagenfunktion verwenden, die mit allen Typen verwendet werden kann, die Sie lesen möchten.

Auf diese Weise können typsichere Code und nicht müssen Weg für die meisten Eingabetypen speziellen Code schreiben:

template<typename T> 
void query(const string &whattoask, T &input) { 
    cout << whattoask << endl; 
    cin >> input; 
    cout << endl; 
} 

int main() { 
    int i; 
    double d; 
    string s; 

    query("An integer: ", i); 
    query("Floating point: ", d); 
    query("A word: ", s); 
} 
+0

In Ordnung!2 für die Vorlage, und das ist, was ich mit gehe. Vielen Dank! – new123456