Commit f39b8de9 authored by Glenn Downing's avatar Glenn Downing
Browse files

another commit

parent 4ef4eedd
Pipeline #423760188 passed with stage
in 1 minute and 46 seconds
......@@ -94,3 +94,367 @@ Zoom: 5.8.6
Virtual Tokens: 6 tokens will bump your letter grade with a minus (e.g., B -> A-)
*/
class Shape {
friend bool operator == (const Shape& lhs, const Shape& rhs) {
return lhs.equals(rhs);}
friend istream& operator >> (istream& lhs, Shape& rhs) {
return rhs.read(lhs);}
friend ostream& operator << (ostream& lhs, const Shape& rhs) {
return rhs.write(lhs);}
private:
int _x;
int _y;
protected:
virtual bool equals (const Shape& rhs) const = 0;
virtual istream& read (istream& in) {
return in >> _x >> _y;}
virtual ostream& write (ostream& out) const {
return out << _x << " " << _y;}
public:
Shape (int x, int y) :
_x (x),
_y (y)
{}
Shape (const Shape&) = default;
virtual ~Shape () = default;
Shape& operator = (const Shape&) = default;
virtual double area () const {
return 0;}
void move (int x, int y) {
_x = x;
_y = y;}};
bool Shape::equals (const Shape& rhs) const {
return (_x == rhs._x) && (_y == rhs._y);}
class Circle : public Shape {
private:
int _r;
protected:
bool equals (const Shape& rhs) const override {
if (const Circle* const p = dynamic_cast<const Circle*>(&rhs))
return Shape::equals(*p) && (_r == p->_r);
return false;}
istream& read (istream& in) override {
return Shape::read(in) >> _r;}
ostream& write (ostream& out) const override {
return Shape::write(out) << " " << _r;}
public:
Circle (int x, int y, int r) :
Shape (x, y),
_r (r)
{}
Circle (const Circle&) = default;
~Circle () = default;
Circle& operator = (const Circle&) = default;
double area () const override {
return 3.14 * _r * _r;}
int radius () const {
return _r;}};
/*
virtual is enabling
1. dynamic binding
2. dynamic_cast
*/
Circle x(...);
cout << x.area(); // Circle's area
Shape* p = &x;
cout << p->area(); // Circle's area
struct A {
virtual void f (int)
{}};
struct B : A
void f (int)
{}};
A* p = new B;
p->f(2); // B::f
struct A {
virtual void f (int) // this does NOT impose the obligation to override
{}};
struct B : A
void g (int)
{}};
A* p = new B;
p->f(2); // A::f
struct A {
virtual void f (long)
{}};
struct B : A
void f (int) // you MUST keep the signature the same between parent and child
{}};
A* p = new B;
p->f(2); // A::f!!!!!!
struct A {
virtual void f (long)
{}};
struct B : A
void f (int) override // you MUST keep the signature the same between parent and child
{}};
A* p = new B;
p->f(2); // doesn't compile
struct A {
virtual void f (int) = 0; // PURE virtual method DECLARATIONS
struct B : A
void f (int) // you MUST override!!!
{}};
A* p = new B;
p->f(2); // B::f
struct A {
virtual void f (long) = 0; // PURE virtual method, in Java this called an ABSTACT method
void A::f (long ...) { // if you define it, it must be outside of the class
...}
struct B : A
void f (int) // you MUST override!!!
{}};
A* p = new B;
p->f(2); // doesn't compile
/*
consequences of an ABSTRACT method in Java
1. children MUST override OR become abstract
2. there is NO definition of the method in the parent
3. the class becomes abstract
*/
/*
consequences of an PURE VIRTUAL method in C++
1. children MUST override OR become abstract
2. definition becomes OPTIONAL, if there's some common code that all children would benefit from
3. the class becomes abstract
*/
#ifdef TEST9
void test9 () {
const Shape* const p = new Circle(2, 3, 4);
Shape* const q = new Circle(2, 3, 5);
assert(*p != *q);
// *q = *p; // illdefined
if (const Circle* const r = dynamic_cast<const Circle*>(p))
if (Circle* const s = dynamic_cast<Circle*>(q)) {
assert(*r != *s);
*s = *r;
assert(*r == *s);}
delete p;
delete q;}
#endif
#ifdef TEST9
void test9 () {
const AbstractShape* const p = new Circle(2, 3, 4);
const AbstractShape* q = new Circle(2, 3, 5);
assert(*p != *q);
// *q = *p; // error: no viable overloaded '='
delete q;
q = p->clone();
assert(*p == *q);
delete p;
delete q;}
#endif
class AbstractShape {
...
public:
virtual AbsractShape* clone () const = 0;
class Circle : public AbstractShape {
...
public:
AbstractShape* clone () const {
return new Circle (*this);}
vector<int> x(10, 2);
class Cell {
Cell (const Cell&) = delete;};
vector<Cell> x(10); // Cell(), 10 times
vector<Cell> y(10, Cell(...)); // Cell(Cell), 10 times
x.push_back(...); // Cell(Cell), once
vector<vector<Cell>> x(10); // vector(), 10 times
vector<vector<Cell>> y(10, vector<Cell>(20)); // vector(vector), 10 times, Cell() 200 times
vector<vector<Cell>> z(10, vector<Cell>(20, ???) // vector(vector), 10 times, Cell(Cell), 200 times
class AbstractShape {
friend bool operator == (const AbstractShape& lhs, const AbstractShape& rhs) {
return lhs.equals(rhs);}
friend istream& operator >> (istream& lhs, AbstractShape& rhs) {
return rhs.read(lhs);}
friend ostream& operator << (ostream& lhs, const AbstractShape& rhs) {
return rhs.write(lhs);}
private:
int _x;
int _y;
protected:
AbstractShape& operator = (const AbstractShape&) = default;
virtual bool equals (const AbstractShape& rhs) const = 0;
virtual istream& read (istream& in) = 0;
virtual ostream& write (ostream& out) const = 0;
public:
AbstractShape (int x, int y) :
_x (x),
_y (y)
{}
AbstractShape (const AbstractShape&) = default;
virtual ~AbstractShape () = default;
virtual double area () const = 0;
virtual AbstractShape* clone () const = 0;
void move (int x, int y) {
_x = x;
_y = y;}};
bool AbstractShape::equals (const AbstractShape& rhs) const {
return (_x == rhs._x) && (_y == rhs._y);}
istream& AbstractShape::read (istream& in) {
return in >> _x >> _y;}
ostream& AbstractShape::write (ostream& out) const {
return out << _x << " " << _y;}
class Circle : public AbstractShape {
private:
int _r;
protected:
bool equals (const AbstractShape& rhs) const override {
if (const Circle* const p = dynamic_cast<const Circle*>(&rhs))
return AbstractShape::equals(*p) && (_r == p->_r);
return false;}
istream& read (istream& in) override {
return AbstractShape::read(in) >> _r;}
ostream& write (ostream& out) const override {
return AbstractShape::write(out) << " " << _r;}
public:
Circle (int x, int y, int r) :
AbstractShape (x, y),
_r (r)
{}
Circle (const Circle&) = default;
~Circle () = default;
Circle& operator = (const Circle&) = default;
double area () const override {
return 3.14 * _r * _r;}
Circle* clone () const override {
return new Circle(*this);}
int radius () const {
return _r;}};
struct A {
virtual void f() = 0;}
void A::f () {}
struct B {}; // did B automatically become abstract: YES!!!!
struct A {
virtual ~A() = 0;} // the only thing this does is to make the class abstract
A::~A() {}
struct B {}; // did B automatically become abstract: NO!!!!
// if we don't a destructor for B, the compiler will!!!
/*
consequences of an PURE VIRTUAL method in C++
1. children MUST override OR become abstract
2. definition in the PARENT becomes OPTIONAL, if there's some common code that all children would benefit from
3. the class becomes abstract
*/
/*
consequences of an PURE VIRTUAL destructor in C++
1. children do not a have override
2. MUST define the destructor in the PARENT
3. the class becomes abstract
*/
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment