shape myShape;Μιά τέτοια εντολή προξενεί μήνυμα λάθους από τον compiler. Μιά κλάση χαρακτηρίζεται αφηρημένη όταν έχει μιά τουλάχιστον virtual συνάρτηση με μηδενικό σώμα, όπως π.χ.
virtual void printEq() const = 0;virtual (εικονική) σημαίνει ότι κάθε υποκλάση που θα δημιουργηθεί, πρέπει να ορίσει την δική της συνάρτηση αυτού του τύπου. Η συγκεκριμένη συνάρτηση είναι αυτή που μου τυπώνει την εξίσωση του σχήματος. π.χ. γιά μιά ευθεία line τυπώνει κάτι σαν το:
aX + bY + c = 0ενώ γιά έναν κύκλο circle τυπώνει κάτι σαν το
X2 + Y2 + aX + bY + c = 0 .Στο σύστημα λοιπόν των τριών κλάσεων που θα φτιάξω, θα υπάρχουν τρεις συναρτήσεις της ίδιας μορφής, αλλά με διαφορετικό σώμα η κάθε μιά:
virtual void printEq() const = 0; χωρίς σώμα στην αφηρημένη κλάση shape
virtual void printEq() const { ... σώμα συνάρτησης της κλάσης line ...}
virtual void printEq() const { ... σώμα συνάρτησης της κλάσης circle ...}
Παραθέτω αμέσως τους ορισμούς των τριών κλάσεων:
#ifndef LINE
#define LINE
/*--------------------------------------------------------------------------
ABSTRACT class shape
----------------------------------------------------------------------------*/
class cmx;
// an experimental abstract class, to be used to implement
// 1) lines defined though two points
// 2) circles defined by center and one point on circle
class shape
{
private:
void copy(const shape & other);
protected:
cmx pts[2];
public:
shape();
shape(const shape & other) ;
shape(cmx* points) ;
shape & operator=( const shape & other );
void setPts(cmx const* ps) ;
void printPoints(bool newline=false) const; // common to both line, circle
virtual ~shape();
virtual void equation(double * c) const = 0;
virtual void PtsFromc( double * c ) = 0;
virtual void printEq() const =0;
virtual double eval( const cmx & z ) const = 0;
};
/*--------------------------------------------------------------------------
class line deriving from abstract class shape
----------------------------------------------------------------------------*/
class line : public shape
{
public:
line();
line(const line & other) ;
line(cmx* points) ;
line & operator=( const line & other );
virtual ~line() ;
virtual void equation(double * c) const ;
virtual void PtsFromc( double * c ) ;
virtual void printEq() const;
virtual double eval( const cmx & z ) const ;
};
/*--------------------------------------------------------------------------
class circle deriving from abstract class shape
----------------------------------------------------------------------------*/
class circle : public shape
{
public:
circle();
circle(const circle & other) ;
circle(cmx* points) ;
circle & operator=( const circle & other );
virtual ~circle() ;
virtual void equation(double * c) const ;
virtual void PtsFromc( double * c ) ;
virtual void printEq() const;
virtual double eval( const cmx & z ) const ;
};
#endif // LINE
void setPts(cmx const* ps) ; void printPoints(bool newline=false) const; // common to both line, circleΗ πρώτη δίνει τιμές στα δύο σημεία που ορίζουν τον κύκλο ή την ευθεία. Η δουλειά είναι η ίδια και στις δύο περιπτώσεις, άρα τοποθετείται εδώ (στην αφηρημένη μητέρα κλάση).
#include "comx.h"
#include "line.h"
#include "cmxFunctions.h"
#include <iostream.h>
#include <math.h>
/*--------------------------------------------------------------------------
ABSTRACT class shape
----------------------------------------------------------------------------*/
shape::shape(){}
shape::~shape(){}
shape::shape(const shape & other) { copy(other);}
shape::shape(cmx* points) {pts[0]=points[0]; pts[1]=points[1];}
shape & shape::operator=( const shape & other )
{
if(this == &other) return *this;
copy(other); return *this;
}
void shape::copy(const shape & other)
{
pts[0]=other.pts[0];
pts[1]=other.pts[1];
}
void shape::setPts(cmx const* ps) {pts[0]=ps[0]; pts[1]=ps[1];}
void shape::printPoints(bool newline) const
{
for(int i=0;i<2;i++)
{
cout << "pt(" << i << ")= " ;
pts[i].print();
cout << " ";
}
if(newline) cout << endl;
}
/*--------------------------------------------------------------------------
class line deriving from abstract class shape
----------------------------------------------------------------------------*/
line::line(){}
line::line(const line & other):shape(other){}
line::line(cmx* points):shape(points){} ;
line & line::operator=( const line & other )
{
shape::operator =(other);
return *this;
}
line::~line() {}
void line::equation(double * c) const
{
c[0] = pts[0].y-pts[1].y;
c[1] = pts[1].x-pts[0].x;
c[2] = -(c[0]*pts[0].x + c[1]*pts[0].y);
}
void line::PtsFromc( double * c )
{
cmx diff(-c[1], c[0] );
double lamda = (-c[2]/(c[0]*c[0]+c[1]*c[1])); // warning
pts[0].x = lamda*c[0];
pts[0].y = lamda*c[1];
pts[1] = pts[0] + diff;
}
void line::printEq() const
{
double c[3];
equation(c);
cout << c[0] << "X + " << c[1] << "Y + " << c[2] << " = 0 \n";
}
double line::eval( const cmx & z ) const
{
double c[3];
equation(c);
return c[0]*z.x + c[1]*z.y+ c[2];
}
/*--------------------------------------------------------------------------
class circle deriving from abstract class shape
----------------------------------------------------------------------------*/
circle::circle(){}
circle::circle(const circle & other):shape(other){}
circle::circle(cmx* points):shape(points){} ;
circle & circle::operator=( const circle & other )
{
shape::operator =(other);
return *this;
}
circle::~circle() {}
void circle::equation(double * c) const
{
c[0] = -2.*pts[0].x;
c[1] = -2.*pts[0].y;
c[2] = 2.*inner(pts[0],pts[1])-inner(pts[1],pts[1]);
}
void circle::PtsFromc( double * c )
{
pts[0].x = - 0.5* c[0];
pts[0].y = - 0.5* c[1];
double critical = inner(pts[0],pts[0])-c[2];
if( critical < 0.0 )
{
cout << " ERROR no real circle " << endl;
pts[1]= pts[0]; // warning ???????
}
else
{
double radius = sqrt( critical );
pts[1].x = pts[0].x + radius;
pts[1].y = pts[0].y;
}
}
void circle::printEq() const
{
double c[3];
equation(c);
cout << "X2+Y2+ " << c[0] << "X + " << c[1] << "Y + " << c[2] << " = 0 \n";
}
double circle::eval( const cmx & z ) const
{
double squares = inner(z,z);
double c[3];
equation(c);
return squares + c[0]*z.x + c[1]*z.y+ c[2];
}
| line::line(const line & other):shape(other){} | Ο κατασκευαστής-αντιγραφής, καλεί απλά τον αντίστοιχο της μητέρας κλάσης. Το ίδιο συμβαίνει και με τον αντίστοιχο κατασκευαστή της circle. |
| line & line::operator=( const line & other ) { shape::operator =(other); return *this; } | Ο τελεστής ισότητας της line καλεί τον αντίστοιχο της μητέρας κλάσης και επιστρέφει το ίδιο το αντικείμενο: (*this) που είναι το αριστερό μέλος της ισότητας. |
| void line::equation(double * c) const |
Συνάρτηση που υπολογίζει τα c[0], c[1], c[2] που παριστούν τους συντελεστές της εξίσωσης της
ευθείας: c[0]x + c[1]y + c[2] = 0. Η ομόνυμη συνάρτηση της circle υπολογίζει τους αντίστοιχους συντελεστές της εξίσωσης του κύκλου: x^2+y^2 + c[0]x + c[1]y + c[2] = 0. Το πρόβλημα είναι ότι σε κάθε κλάση χρειάζεται ένας διαφορετικός τρόπος υπολογισμού αυτών των συντελεστών από τους δύο μιγαδικούς pts[0] και pts[1]. Ετσι κάθε κλάση έχει την δική της συνάρτηση γι αυτόν τον υπολογισμό. |
| void line::PtsFromc( double * c ) |
Συνάρτηση που κάνει την αντίστροφη δουλειά από την προηγούμενη. Δηλαδή υπολογίζει τα
σημεία pts[0] και pts[1] από τα c[0], c[1], c[2] που παριστούν τους συντελεστές
της εξίσωσης της ευθείας: c[0]x + c[1]y + c[2] = 0. Η ομόνυμη συνάρτηση της circle κάνει τα ανάλογα για τον κύκλο. |
| void line::printEq() const |
Συνάρτηση που τυπώνει την εξίσωση της ευθείας Η ομόνυμη συνάρτηση της circle κάνει τα ανάλογα για τον κύκλο. |
#include "comx.h"
#include "line.h"
#include <iostream.h>
int main(int argc, char* argv[])
{
cmx a[2] = { cmx(1.,1.), cmx( 1.0, 0.0) };
cmx b[2] = { cmx(-1.,0.), cmx( 0.0, 1.0) };
line aLine(a);
line bLine(b);
aLine.printEq();
bLine.printEq(); // sign printing problem ??
double c[3] = { -1. , 1. , -1. };
line cLine;
cLine.PtsFromc(c);
cLine.printEq();
circle aCircle(a);
circle bCircle(b);
aCircle.printEq();
bCircle.printEq();
circle cCircle;
cCircle.PtsFromc(c);
cCircle.printEq();
return 0;
}
shape & shape::operator=( const shape & other )
{
if(this != &other) copy(other);
return *this;
}
Εξήγησε τι είναι το this και τι κάνει η συνάρτηση αυτή.