Sonntag, Dezember 15, 2019

Beste Ansatz für Struktur-Polymorphismus in C

Schreibe ich eine einfache 2d-Vektor-Objekt. Es müssen x-und y-Komponenten, und die Länge, Kreuz-Produkt, etc. Methoden. Die Sache ist die, ich will haben die Struktur zu haben, die vielen möglichen Typen (char, int, float, double, etc.). Ich Frage mich, was wäre die beste Wahl, design-Weise, um die Interaktion mit dem Objekt? Hier ist, was ich bin derzeit in Erwägung:

1. Haben Sie den Benutzer übergeben, der ein vector-Objekt um spezielle Funktionen, wie:

Vector2Dt_Dot(Vec2Dt* vector1, Vec2Dt* vector2);

wobei ‚t‘ der Typ des Vektors. Jedoch, das problem bei diesem Ansatz ist, dass es verbietet verschiedene Arten von Interaktion mit jedem anderen, so dass ich nicht sagen konnte, berechnen Sie das Skalarprodukt a float vector2d und ein Doppel vector2d. Ein zweiter Ansatz, und was ich bin Neigung in Richtung:

2. Haben die Benutzer-pass vector-Objekt(s) als void-Zeiger, zusammen mit Ihrem Typen, wie:

Vector2D_Dot(void* vector1, unsigned vector1_type, void* vector2, unsigned vector2_type);

offensichtlich dieser Ansatz ist kompakter API-Weise und löst auch das problem von oben, aber auf Kosten von ein paar zusätzliche Parameter und geben Sicherheit.

Möglicherweise gibt es andere Lösungen, ich bin mir nicht bewusst, aber diese sind die, die ich derzeit in Betracht ziehen. Was denken Sie, ist der beste Ansatz, um dieses?

  • die Frage ist tagged c, nicht c++
  • Verwenden Sie nicht die void * alternative; es gibt zu viele Möglichkeiten, Sie können Fehler machen, die der compiler nicht abfangen (weil jeder Zeigertyp umgewandelt werden können, um eine void * in C oder C++). Zu einer Zeit, diese Frage (kurz) hatten einen C++ – tag und für eine längere Zeit zu verwenden, C++ – Referenz-Typ notation. Wenn C++ ist relevant, erwägen Sie, eine vector<vector<yourtype> >.
  • leffler: Ja, das war mein Fehler. Ich Wechsel zwischen C und C++ oft. Ich würde auf jeden Fall verwenden Sie einen Vektor-ähnliche Oberfläche, wenn es eine option in C.
InformationsquelleAutor Shokwav | 2013-08-24

3 Kommentare

  1. 15

    Was Sie tun können, ist die Verwendung von polymorphen Objekten. Definieren Sie die Strukturen, wie diese:

    #define INT_TYPE 0
    #define DOUBLE_TYPE 1
    //more type constants
    
    typedef struct Vector2D {
        int type;
    } Vector2D;
    
    typedef struct Vector2D_int {
        Vector2D super;
        int x, y;
    } Vector2D_int;
    
    typedef struct Vector2D_double {
        Vector2D super;
        double x, y;
    } Vector2D_double;
    
    //more typed vector structures

    Dann Sie können schreiben Sie Ihre Funktionen zu akzeptieren Vector2D Zeiger, untersuchen Ihre jeweiligen Felder und warfen Sie auf den entsprechenden typisierten Variante, um den Zugriff auf die Nutzdaten.

    double Vector2D_length(const Vector2D* vector) {
        if(vector->type == TYPE_INT) {
            const Vector2D_int* intVector = (Vector2D_int*)vector;
            return sqrt(intVector->x * intVector->x + intVector->y * intVector->y);
        }
        if(vector->type == TYPE_DOUBLE) {
            const Vector2D_double* doubleVector = (Vector2D_double*)vector;
            return sqrt(doubleVector->x * doubleVector->x + doubleVector->y * doubleVector->y);
        }
        //other cases follow
    }

    Dies ist Polymorphismus codiert von hand. Alles, was Sie brauchen, um sicherzustellen, ist, dass die type Feld ist immer auf den korrekten Wert gesetzt (gesetzt einmal, wenn ein Vektor eingegeben wird erstellt).

    Der Vorteil dieses Ansatzes auf Ihre zweite Idee ist, dass Sie nicht zu Durchlaufen haben, um die Art der Vektoren eine weitere variable, die mit Ihren Vektoren mühsam und fehleranfällig.

    Als alternative können Sie festlegen, Ihren type Feld mit einem Zeiger auf eine Struktur von Funktionszeigern. Erstellen Sie ein Objekt von dieser Funktion-Zeiger-Struktur pro getippt, Vector-Art, die Sie definieren, und es verwenden, um die lookup-Funktion zu verwenden, mit dem gegebenen Vektor. Dieser Ansatz wäre sehr nahe an dem, was C++ bietet unter der Haube.

    • Fantastisch! Danke.
  2. 3

    Können Sie eine variable Argumentliste, dessen Prototyp kodiert wird, zum Beispiel als:

    int  xyz(int a, ...);

    Dieser Stil muss einem angegebenen parameter, in diesem Beispiel a gefolgt von einer beliebigen Anzahl von Parameter, deren Datentypen können zur Laufzeit bestimmt werden.

    Finden Sie die Funktionen und Objekte: va_list; va_start; va_args; und va_end für eine vollständige Beschreibung, wie die Prozess-variable argument-Listen.

    Hoffe, das hilft. Wenn Fragen über va_list usw. Fragen Sie bitte nach.

  3. 0

    Was ich eigentlich ging, war Folgendes:

    Erstellte ich eine base Vector2D-Klasse, mit den folgenden layout:

    struct Vector2D_Base;
    typedef struct Vector2D_Base{
        M_double (*Vector2D_Get_X)(struct Vector2D_Base* vec);
        M_double (*Vector2D_Get_Y)(struct Vector2D_Base* vec);
    } Vector2D;

    Wie Sie sehen können, dies erlaubt den generischen Vektor-Funktionen aufrufen, diese zu bekommen, die von abgeleiteten Klassen “ x-und y-Werte umgewandelt, um Doppel -, die verhindert, dass die generische Funktion von Gedanken über den Unterschied zwischen Größen von Typen wie char und float. Dann jede abgeleitete Klasse:

    #define DEFINE_VECTOR2D(type, name)\
    typedef struct{\
    Vector2D_Base vec_base;\
    type x, y;\
    } Vector2D##name\

Kostenlose Online-Tests

Letzte Fragen

Tun ItemView löst Blase?

Ich habe eine CompositeView für eine Tabelle. Ich habe Trigger-set in der Kind-ItemView für jede Zeile... var TableRow = Marionette.ItemView.extend({ tagName:...

Wie kann ich untersuchen, WCF was 400 bad request über GET?

Die folgenden WCF-endpoint funktioniert gut mit dem WCF test client: AssetList ListFlaggedAssets(short processCode, string platform, string endpoint = "null", string portalId = "null", int...

Bei der Verwendung von UUIDs, sollte ich auch mit AUTO_INCREMENT?

Wir bauen eine neue web-app, die eine offline-iPad - /Android-app-version auf einer Reihe von lokalen Geräten, die Einsätze mit neuen Daten. Als solche benötigen...

Actionscript-Objekt, das verschiedene Eigenschaften

Wie kann ich die Anzahl der Eigenschaften in einer generischen Actionscript-Objekt? (Wie die Array-Länge) InformationsquelleAutor Fragsworth | 2011-01-15

Wie plot mehrere Graphen und nutzen Sie die Navigations-Taste im [matplotlib]

Die neueste version von matplotlib erstellt automatisch Navigations-buttons unter den graph. Aber die Beispiele, die ich finden alles im Internet zeigen, wie erstellen Sie...