2017-01-12 2 views
0

Ich habe eine Funktion, die eine void* zurückgibt. Gerade jetzt, wenn diese Funktion abgeschlossen ist, wird ein UINT16* Array als void * zurückgegeben. Das Array UINT16 wird am Anfang der Methode erstellt, aber jetzt muss ich den Array-Typ bestimmen und stattdessen diesen Typ erstellen. Beispielsweise findet eine Datenverarbeitung statt und bestimmt, dass ein Array vom Typ int erstellt werden soll, sodass ein int-Array erstellt und zurückgegeben wird. Andere Typen wie Double und Byte können ebenfalls erstellt werden.Erstellen eines C++ - Arrays, das verschiedene Typen sein kann

Wie gehe ich vor?

Mein aktueller Code hat

UINT16* data_out = new UINT16[arraySize]; 

Ich weiß, dass ich eine große schaffen kann, wenn/else oder switch-Anweisung, aber ich frage mich, ob es einen besseren Weg gibt.

+3

[boost :: variant] (http://www.boost.org/doc/libs/1_63_0/doc/html/variant.html). –

+0

Verwenden Sie Schalter, wenn Ihr Problem nur 'if/else' ist – Raindrop7

+0

Vorlage Spezialisierung – nikau6

Antwort

0

Ähm ... tut mir leid, wenn das eher eine Frage als ein Kommentar ist ...: | Ich kann keinen Kommentar abgeben.

Wenn Sie eine Kernlösung wünschen, können Sie eine verknüpfte Listenklasse erstellen, die verschiedene Typen von Steckdosen hat. Grundsätzlich statt nur eine UINT_64* next; zu haben, würden Sie haben:

int* nextInt; 
double* nextDouble; 

Und so weiter und so fort. Wenn Sie dann ein Double mit Tags versehen möchten, können Sie einfach den nächsten Double-Outlet verwenden. Um herauszufinden, zu welchem ​​Ausgang es gehen soll, überprüfe einfach, ob der int auf irgendwas zeigt; Wenn nicht, geh weiter. Ich weiß, das scheint eine wirklich nervige und sperrige Option zu sein, aber ich nehme an, es macht den Job.

0

Void * Funktionen can be fun and do some very interesting Dinge ... (Sorry für eine frühere Antwort von mir verbindet, aber es ist das erste Beispiel, das zu mir kam.) Aber sie sind nicht sicher und haben Null Typprüfung ...

In Ihrem Fall brauchen Sie nur eine einfache Template-Funktion und das Schlüsselwort auto. Etwas wie:

#include <iostream> 
#include <iomanip> 

template <typename T> 
T * returnAnArray (int size) { 
    T * data_out = new T[size]; 
    return data_out; 
} 

int main() { 
    int size = 3; 
    auto array = returnAnArray<double>(3); 

    for(int i=0;i<size;++i) 
     array[i] = 0; 

    for(int i=0;i<size;++i){ 
     std::cout << std::setprecision(2); 
     std::cout << array[i] << std::endl; 
    } 

    delete [] array; 

    return 0; 
} 

Ich habe etwas Spaß haben, und erstellen Sie haben eine void * Funktion (aber es induziert, was nicht definiertes Verhalten zu sein scheint):

template <typename T> 
void * returnVoidPointerToArray(int size) { 
    return new T[size]; 
} 

Die Funktion, wenn verwendet, muss gegossen werden, damit sie etwas zurückgeben konnte:

auto chArray = (char*)returnVoidPointerToArray<char>(size); 

Aber die Ausgabe wie folgt aussieht:

5.00 
5.00 
5.00 
ggg 
ggg 
ggg 
Program ended with exit code: 0 

Beachten Sie, wie double sind ein einzelner Wert, aber die gleiche Funktion scheint ein 2d-Array von Zeichen initialisiert ... Seltsam, oder?

Und, wie der Kommentator sagte, wahrscheinlich eine gute Idee, einzigartige Zeiger zu verwenden. :)

+1

Besser, 'return std :: unique_ptr (Größe);'. – Jarod42

+0

"aber die gleiche Funktion scheint ein 2d Array von Zeichen zu initialisieren ..." - das wäre, weil Sie das Ergebnis auf 'char *', nein? – davmac

1

So etwas vielleicht?

Dies wird nicht funktionieren, aber danke für die Verbesserung. In der Tat könnte es funktionieren, aber Sie müssen den Typ kennen, der von Foo zurückgegeben wird, um es verwenden zu können. Aber der Typ ist innerhalb Foo bestimmt, das ist ein ernster Konzeptionsnachteil.Sie sollten überdenken, wie Sie das wollen.

enum class ArrayType 
    { 
     Int, 
     Double 
    }; 

    template <typename T> 
    T* CreateArray(size_t size) 
    { 
     T* t = new T[size]; 
     return t; 
    } 

    void* Foo(param1, param2, etc..) 
    { 
     size_t size; 
     ArrayType type; 

     .. Do things to determine the type 

     switch(type) 
     { 
      case ArrayType::Int: 
       return CreateArray<int>(size); 

      case ArrayType::Double: 
       return CreateArray<double>(size); 

      default: 
       return 0; 
     } 

     return 0; 
    } 
0

Ich bin nicht sicher, warum Sie einen praktisch nicht typisierten Rückgabewert mit void* verwenden, aber nehmen wir an, dass es Gründe dafür.

Es gibt eigentlich zwei Probleme, nämlich das Array zu erstellen und es dann zu verwenden.

Wenn Sie ein Array von verschiedenen Typen basierend auf einer Logik erstellen, müssen Sie sich irgendwie mit if oder switch() befassen; Wie sonst würden Sie die Logik ausdrücken, die den gewünschten Ergebnistyp bestimmt? Aber, wenn Sie möchten, können Sie auch etwas wie result = malloc(nrOfItems*sizeOfItem) verwenden und sizeOfItem für jede Logik bestimmen, die Sie mögen, sogar basierend auf arithmetischen Berechnungen.

Die interessantere oder kritischere Sache ist, wie der Aufrufer das Ergebnis der jeweiligen Funktion verwenden soll, da der Zugriff auf die Elemente eines Arrays Wissen über den Typ oder die Größe der Elemente in ihm erfordert.

Nehmen wir zum Beispiel den folgenden Code:

void* getSomeItems() { 
    if (std::rand() > 100000) 
    return new char[200]; 
    else 
    return new double[200]; 
} 

int main() { 
    void* someItems = getSomeItems(); 
    double c = ((double*)someItems)[199]; // Critical! 
    // how shall we know if element type is double? 
    // if rand() decided to create items of type char, 
    // this code accesses non allocated memory 
    ... 

So können, wenn Ihre Funktion, auf dem die Informationen zurückgeben Art (und eigentlich auch die Größe des Arrays), der Rückgabewert erstellt wurde ist fast überflüssig.

würde ich vorschlagen, nicht void* für diesen Einsatz. Wenn Sie den Typ vor dem Aufruf der Funktion kennen, können Sie Vorlagen, Vektoren oder andere Dinge verwenden. Wenn Sie den Typ und/oder die Größe vor dem Aufruf nicht kennen, geben Sie eine Struktur zurück, die neben dem zugewiesenen Array auch Informationen zu Typ/Größe enthält.

BTW: vergessen Sie nicht, das Ergebnis am Ende delete[]/free. vielleicht

Verwandte Themen