2016-10-29 5 views
1

Ich habe ein Buch über Computergestützte Geometrie gelesen. In diesem Buch gibt es einen Einführungsteil, in dem beschrieben wird, wie man eine grundlegende Vertex-Datenstruktur implementiert. Die Route, auf die das Buch folgt, ist die folgende.Mehrfache Vererbung C++, wie funktioniert das Casting?

Es zunächst erläutert, wie eine Liste Datenstruktur zu implementieren, und insbesondere die Knotenschnittstelle wird wie folgt

class Node { 
public: 
    Node(); 
    Node* getNext(); 
    Node* getPrev(); 
    void setNext(Node *x); 
    void setPrev(Node *x); 
    Node* insert(Node *x); 
    Node* remove(); 
    void splice(Node *x); 
private: 
    Node *next; 
    Node *prev; 
}; 

Dann wird eine Point-Klasse implementiert wird, mit der folgenden Schnittstelle

class Point2D { 
public: 
    Point2D(); 
    Point2D(double x, double y); 
    Point2D(const Point2D& p); 
    void setX(double x); 
    void setY(double y); 
    double getX(); 
    double getX() const; 
    double getY(); 
    double getY() const; 
    Point2D operator+(Point2D& p); 
    Point2D operator-(Point2D& q); 
    Point2D operator-(); 
    Point2D& operator=(const Point2D& p); 
    bool operator==(Point2D& p); 
    bool operator!=(Point2D& p); 
    bool operator>(Point2D &p); 
    bool operator>=(Point2D &p); 
    bool operator<(Point2D &p); 
    bool operator<=(Point2D &p); 
    friend Point2D operator*(double c, Point2D p); 
    double getDistance(Point2D& q); 
    double getLength(); 
    int orientation(Point2D p, Point2D q); 
    int classify(Point2D p, Point2D q); 
private: 
    double x; 
    double y; 
}; 

Und zuletzt haben wir die Scheitelpunktklasse

class Vertex : public Node, public Point2D { 
public: 
    Vertex(double x, double y); 
    Vertex(Point2D x); 
    Vertex *cw(); 
    Vertex *ccw(); 
    Vertex *neighbour(int direction); 
    Point2D getPoint(); 
    Vertex *insert(Vertex *v); 
    Vertex *remove(Vertex *v); 
    void splice(Vertex *v); 
    friend class Polygon; 
}; 

Let's spezifisch zu den Methoden

Point2D Vertex::getPoint() { 
return *((Point2D*)this); 
} 

Vertex *Vertex::insert(Vertex *v) { 
return (Vertex*)(Node::insert(v)); 
} 

Wie Sie sehen können, gibt es einige Besetzung beteiligt. Nun, wenn ich Einzelvererbung hätte, wüsste ich, dass alle Datenelemente wie "gestapelt" wären, und das Casting würde darin bestehen, einen Offset von der Basisadresse zu berechnen, die von der Basisklasse gegeben wird.

Like:

class A { 
public: int a; 
}; 

class B : public A { 
public: int b; 
}; 

Und irgendwo

B b; 
A a = *(A*)&b; 

In diesem Fall habe ich das sagen würde, b eine Basisadresse hat (lassen Sie uns Name solche Adresse b_addr, auf A das Gießen (ist nicht wirklich ein Casting, aber trotzdem ... vielleicht hast du meinen Punkt) würde bedeuten, von b_addr zu b_addr + 4 zu "überdenken". Allerdings bin ich nicht sicher, wie es diese Berechnung im Falle der Mehrfachvererbung funktionieren würde. Kann jemand erklären mir?

+0

Die Objekte sind immer noch gestapelt. Wenn Sie einen Cast ausführen, kennt der Compiler die relative Position der jeweiligen Basisklasse und verschiebt "this" darauf. –

+0

Gibt es stattdessen etwas im umgekehrten Fall zu wissen? wenn Sie von einem Basisobjekt auf ein Derivat umwandeln? – user8469759

+0

Nein, es gibt nichts anderes zu wissen. Wenn das Objekt "A" "x" Bytes von dem Objekt "B" "gestapelt" ist, beinhaltet das Gießen von "A" nach "B" das Hinzufügen von "x" Bytes zu der Adresse und "B" zu "A" beinhaltet das Subtrahieren von x' Bytes von der Adresse. –

Antwort

0

Bei Einfachvererbung:

struct A { int a; }; 
struct B : A { int b; }; 
struct C : B { int c; }; 
C c; 

Hier c, (B&)c und (A&)c die gleiche Adresse haben; Es gibt keinen Offset zum Hinzufügen oder Subtrahieren von Casting von einem zu irgendeiner anderen Struktur der Hierarchie.

Bei Mehrfachvererbung:

struct A { int a; }; 
struct B { int b; }; 
struct C : A,B { int c; }; 
C c; 

Hier c und (A&)c die gleiche Adresse haben, aber Adresse des (B&)c von sizeof(A) von Adresse c offsetted wird. Auch (char*)&c.c == (char*)&c + sizeof(A) + sizeof(B).

+0

Letzte Gleichheit ist nicht wahr, es sei denn, es wird char * – RiaD

+0

@RiaD: das ist richtig, danke, Antwort aktualisiert. – shrike