2 Stimmen

Strukturen und Operatorüberladung in C++

struct PT 
{   
  double x, y;  
  PT() {}  
  PT(double x, double y) : x(x), y(y) {}  
  PT(const PT &p) : x(p.x), y(p.y)    {}  
  PT operator + (const PT &p)  const { return PT(x+p.x, y+p.y); }  
  PT operator - (const PT &p)  const { return PT(x-p.x, y-p.y); }  
  PT operator * (double c)     const { return PT(x*c,   y*c  ); }  
  PT operator / (double c)     const { return PT(x/c,   y/c  ); }  
};

Dieser Codeschnipsel stammt aus http://stanford.edu/~liszt90/acm/notebook.html#file8 . Ich bin nicht in der Lage, dieses Stück Code zu verstehen. Jemand bitte erklären diese. Ich weiß, dass es sich um Operatorüberladung handelt, aber ich kann nicht verstehen, wie genau die Operatorüberladung abläuft.

Kann jemand auch diese Zeilen erklären:

PT() {}  
PT(double x, double y) : x(x), y(y) {}  
PT(const PT &p) : x(p.x), y(p.y)    {}

Haben Strukturen auch Konstrukteure?

2voto

Michael J Punkte 7247
double x, y;  

Deklariert zwei lokale Klassenvariablen, aus denen die Klasse besteht.

PT() {}  

Standard-Konstruktor. Ermöglicht die Erstellung eines PT ohne Argumente.
z.B. --> PT myObj;

PT(double x, double y) : x(x), y(y) {}  

Konstruktor zur Erzeugung eines Punktes aus zwei Doubles.
z.B. --> PT myObj(3.5, 9.0);
Nach der Erklärung --> PT(double x, double y) : x(x), y(y) {}
Wir haben eine Initialisierung .--> PT(double x, double y) : x(x), y(y) {}
x(x) ist gleichbedeutend mit this->x = x;
d.h. die Klassenvariable "x" mit dem Konstruktorparameter "x" initialisieren. Es ist etwas verwirrend, dass sie den Parametern denselben Namen wie den Klassenvariablen gegeben haben. Ein besseres Beispiel hätte lauten können:

    PT(double xInit, double yInit) 
    : x(xInit)
    , y(yInit) 
    {
    }  

    PT(const PT &p) : x(p.x), y(p.y)    {}  

Kopierkonstruktor zur Erstellung eines PT-Objekts aus einem anderen PT-Objekt
z.B. --> PT myOtherObj(myObj);

PT operator + (const PT &p)  const { return PT(x+p.x, y+p.y); }  
PT operator - (const PT &p)  const { return PT(x-p.x, y-p.y); }

Additions- und Subtraktionsoperatoren, um die Summe oder die Differenz von zwei Punkten zu einem dritten zu bilden.
z.B. -->

    PT sumObj  = myObj + myOtherObj;
    PT diffObj = myObj - myOtherObj;

PT operator * (double c) const { return PT(x*c, y*c ); }
PT operator / (double c) const { return PT(x/c, y/c ); }

Multiplikations- und Divisionsoperatoren, um einen Punkt mit einer Konstanten zu multiplizieren (oder zu dividieren).
z.B. -->

    PT prodObj = myObj * 2.7;
    PT divObj  = myObj / 8.0;

1voto

CapelliC Punkte 58673

Zeilen 4 und 5 sind Konstrukteure und die Syntax x(x) hebt eine idiomatische Art und Weise hervor, den Konstruktor der Mitgliedsvariablen aufzurufen (z.B. pass down).

Beachten Sie, dass is no einen anderen Bezeichner für einen formalen Parameter verlangt. Eine Zuweisung innerhalb des Konstruktorkörpers würde eine andere Benennung erfordern, da ein formaler Parameter die Mitgliedsvariablen "versteckt". D.h. wir würden z.B. benötigen

 PT(double x_, double y_) { x = x_; y = y_; }  

Beachten Sie auch, dass wir auf diese Weise no Aufruf des Konstruktors von Mitglied x, sondern der Zuweisungsoperator. Für POD-Daten gibt es keinen Unterschied, aber die Syntax erlaubt beliebige, benutzerdefinierte Memberfunktionen für Klassen wie PT .

0voto

Joel Falcou Punkte 6057

Wann immer der Compiler auf einen Aufruf der Form

a + b;

ruft es tatsächlich

a.operator+(b)

wenn eine solche Methode im Typ von a existiert oder

operator+(a,b)

wenn eine solche freie Funktion existiert.

Die Syntax "Operator" bedeutet lediglich, dass Sie den genannten Operator gerade überladen. (Für jeden gültigen Operator natürlich).

0voto

iammilind Punkte 64857

Das Überladen von Operatoren ist ein Konzept, bei dem die üblichen Operatoren wie + , '- , '* , ... werden auch für Strukturen/Klassen 'überladen'. Im Allgemeinen ist diese Möglichkeit nur für die ursprünglichen Datentypen verfügbar wie int , double , ....

Hier in struct PT sind die Operator-Methoden einfach definiert. Sie treten in Kraft, sobald Sie das Objekt von PT und verwenden Sie es. z.B.

PT pt1, pt2;
PT pt3 = pt1 + pt2;  // pt1.operator +() has instantiated

0voto

6502 Punkte 108136

Wahrscheinlich ist es einfacher, das Überladen von Operatoren zu verstehen, wenn man sich die Nicht-Mitglieder-Version davon ansieht. Wenn Sie dem Compiler sagen wollen, was Sie meinen, wenn Sie zwei PT Objekte können Sie Folgendes schreiben:

PT operator + (const PT& a, const PT& b)
{
    return PT(a.x + b.x, a.y + b.y);
}

Der obige Code besagt einfach, dass, wenn der Compiler den Ausdruck a + b wobei beide a et b sind PT Instanzen, dann ist das Ergebnis eine neue PT Instanz, die von dieser Funktion berechnet wird.

Sie können das Gleiche für einige andere Operatoren tun und so dafür sorgen, dass sich Ihre Klasseninstanzen in Bezug auf die normale Mathematik "natürlicher" verhalten.

Der Code, den Sie haben, ist derselbe, aber in einer etwas unnatürlichen asymmetrischen Form geschrieben, in der Sie beschreiben, was zu tun ist, wenn ein anderes Objekt zum Beispiel zu this Objekt. Ein solcher Ansatz sieht für binäre mathematische Operatoren recht merkwürdig aus, da beispielsweise der erste oder zweite Operand einer Addition nichts Besonderes ist und sich beide auf derselben logischen Ebene befinden. Die Asymmetrie für die this Konzept ist jedoch Teil der C++-DNA und es gibt nicht viel, was man dagegen tun kann. Theoretisch ist es eine schlechte Asymmetrie für jede Methode, die auch nur einen Parameter benötigt, aber in der Praxis kann man auch mit diesem Ansatz noch eine ganze Weile weitermachen.

Andere Teile des Codes sind:

// Default constructor. Will create an object without any parameter
// and the x, y values will be uninitialized. This is generally a bad
// practice and you should avoid it unless there are very specific and
// measured performance reasons for doing that.
// Having a constructor accepting no parameters is sometimes necessary
// if you want for example to be able to put your instances in an std::vector
// and you may need to call .resize() on the vector. Even if you will always
// just shrink the vector the compiler will require anyway a default
// constructor because there's no shrink-only call on vectors and any
// resize operation is assumed to be potentially growing the size.
PT() {}

// Copy constructor. This is totally unneeded... when you don't
// put a copy constructor in a class the C++ compiler will automatically
// generate exactly this code (i.e. a constructor that will copy-construct
// all members). In general this may be or may not be the right thing
// depending on the class, but in this case is exactly what you want
// and there was no need for this code.
// As a general rule if you see a copy constructor, an assignment operator
// or a destructor but you don't see all three of them in a class then
// most probably there's something wrong. It's difficult to think to
// a real use case in which you need some of them but not all three of
// them... in this case for example the mistake is that this code could
// and should have been omitted.
PT(const PT &p) : x(p.x), y(p.y) {}

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X