CS 330 Lecture 29 – Virtuality in C++ and Overloading Builtin Operators
Agenda
- what ?s
- no class Friday
- program this
- http://www.parashift.com/c++-faq/refs-vs-ptrs.html
- cosmic superclass
- overriding with virtual
- implementing Polynomial::solve
- pure virtual
- the means of dynamic dispatch
- overloading builtin operators
- a FasterString class
- deconstructors
Pulse
Student evaluations are just numbers, but I like to hear anecdotes too. Please take a moment to think about how this course is run: grading scale, homework setup, topics, and so on. Now, suppose you’re teaching a classroom full of up-and-coming computer scientists.
- What would you retain?
- What would you do differently?
Opportunity
- Author and manager of software engineers Michael Lopp is speaking Thursday night at 6 PM in Phillips 117. If you attend and write a quarter sheet response to his talk, you’ll get 2 extra participation points. If you ask a (real) question, you can have one more week (until May 10) to submit an assignment. Asking a real question usually requires advanced preparation: http://www.randsinrepose.com. You can complete both.
Program This
Rewrite the following using C++ references:
template<typename T> void swap(T *a, T *b) {
T tmp = *a;
*a = *b;
*b = tmp;
}
Code
Functions.h
#ifndef FUNCTIONS_H
#define FUNCTIONS_H
class Function {
public:
virtual double evaluateAt(double x) const = 0;
};;;;
class SineFunction : public Function {
public:
double evaluateAt(double x) const;
};
class Polynomial : public Function {
public:
Polynomial(int degree);
double evaluateAt(double x) const;
int GetDegree() const;
void setCoefficient(int i, double coefficient);
virtual double *getRoots() const;
private:
int degree;
protected:
double *coefficients;
};
class LinearFunction : public Polynomial {
public:
LinearFunction(double slope, double y_intercept);
double *getRoots() const;
};
class QuadraticFunction : public Polynomial {
public:
QuadraticFunction(double a, double b, double c);
double *getRoots() const;
};
#endif
Functions.cpp
#include <cmath>
#include <iostream>
#include "Functions.h"
Polynomial::Polynomial(int degree) :
degree(degree) {
coefficients = new double[degree + 1];
}
int Polynomial::GetDegree() const {
return degree;
}
double Polynomial::evaluateAt(double x) const {
double sum = 0.0;
double xpow = 1.0;
for (int i = 0; i <= degree; ++i) {
sum += xpow * coefficients[i];
xpow *= x;
}
return sum;
}
void Polynomial::setCoefficient(int i, double coefficient) {
coefficients[i] = coefficient;
}
double *Polynomial::getRoots() const {
std::cerr << "I don't know how to do that." << std::endl;
return NULL;
}
LinearFunction::LinearFunction(double slope,
double y_intercept) :
Polynomial(1) {
setCoefficient(0, y_intercept);
setCoefficient(1, slope);
}
QuadraticFunction::QuadraticFunction(double a,
double b,
double c) :
Polynomial(2) {
setCoefficient(0, c);
setCoefficient(1, b);
setCoefficient(2, a);
}
double *LinearFunction::getRoots() const {
double *roots = new double[1];
roots[0] = -coefficients[0] / coefficients[1];
return roots;
}
double *QuadraticFunction::getRoots() const {
double *roots = new double[2];
roots[0] = (-coefficients[1] + sqrt(coefficients[1] * coefficients[1] - 4.0 * coefficients[2] * coefficients[0])) / 2.0 * coefficients[2];
roots[1] = (-coefficients[1] - sqrt(coefficients[1] * coefficients[1] - 4.0 * coefficients[2] * coefficients[0])) / 2.0 * coefficients[2];
return roots;
}
double SineFunction::evaluateAt(double x) const {
return sin(x);
}
/* ------------------------------------------------------------------------- */
graph.cpp
#include <iostream>
#include "Functions.h"
/* ------------------------------------------------------------------------- */
void draw(const Function &f);
int main(int argc, char **argv) {
LinearFunction f(1.0, 0.0);
QuadraticFunction xsquared(1.0, 0.0, -1.0);
Polynomial p(3);
p.setCoefficient(0, 0.0);
p.setCoefficient(1, 0.0);
p.setCoefficient(2, 0.0);
p.setCoefficient(3, 1.0);
draw(SineFunction());
return 0;
}
/* ------------------------------------------------------------------------- */
void draw(const Function &f) {
const int NROWS = 21;
const int NCOLS = 51;
char plot[NROWS][NCOLS];
for (int r = 0; r < NROWS; ++r) {
for (int c = 0; c < NCOLS; ++c) {
plot[r][c] = ' ';
}
}
for (int c = 0; c < NCOLS; ++c) {
plot[NROWS / 2][c] = '-';
}
for (int r = 0; r < NROWS; ++r) {
plot[r][NCOLS / 2] = '|';
}
plot[NROWS / 2][NCOLS / 2] = '+';
for (int c = 0; c < NCOLS; ++c) {
double x = c / (NCOLS - 1.0) * 6.0 - 3.0;
double y = f.evaluateAt(x);
int r = (int) (y * NROWS * 0.5 + NROWS * 0.5);
if (r >= 0 && r < NROWS) {
plot[r][c] = '.';
}
}
for (int r = NROWS - 1; r >= 0; --r) {
for (int c = 0; c < NCOLS; ++c) {
std::cout << plot[r][c];
}
std::cout << std::endl;
}
}
/* ------------------------------------------------------------------------- */
makefile
Note to copy and pasters: makefile rules need to be indented with real tabs, not spaces.
all: graph
Functions.cpp: Functions.h
Functions.o: Functions.cpp
g++ -c Functions.cpp
graph: graph.cpp Functions.o Functions.h
g++ -o graph graph.cpp Functions.o
run: run_graph
run_graph:
./graph
clean:
rm -f *.o
roots.cpp
#include <iostream>
#include "Functions.h"
void printRoots(const Polynomial &p) {
double *roots = p.getRoots();
if (roots != NULL) {
for (int i = 0; i < p.GetDegree(); ++i) {
std::cout << "roots[" << i << "]: " << roots[i] << std::endl;
}
}
}
int main(int argc, char **argv) {
Polynomial xcubed(3);
xcubed.setCoefficient(0, 0.0);
xcubed.setCoefficient(1, 0.0);
xcubed.setCoefficient(2, 0.0);
xcubed.setCoefficient(3, 1.0);
printRoots(xcubed);
printRoots(QuadraticFunction(1.0, 0.0, 0.0));
printRoots(LinearFunction(1.0, 3.0));
std::cout << "0.0f * -0.0f: " << 0.0f * -0.0f << std::endl;
return 0;
}
Haiku
“What makes OOP?”
“Superpolymorphitance.”
Your next interview.
“Superpolymorphitance.”
Your next interview.