1 / 106

The Quarks of Object-Oriented Development Deborah J. Armstrong, CACM 49(2006), vol.2 p123-128

The Quarks of Object-Oriented Development Deborah J. Armstrong, CACM 49(2006), vol.2 p123-128. Using Objects. Internal, and User-defined Data-types (Classes) Declaration, Definition, Initialization Usage via Name, Reference, or Pointer

suzannef
Download Presentation

The Quarks of Object-Oriented Development Deborah J. Armstrong, CACM 49(2006), vol.2 p123-128

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. The Quarks of Object-Oriented DevelopmentDeborah J. Armstrong, CACM 49(2006), vol.2 p123-128

  2. Using Objects Internal, and User-defined Data-types (Classes) Declaration, Definition, Initialization Usage via Name, Reference, or Pointer Manipulating Objects in Expressions via Operators or Functions Objects as Function Parameters Scope and Lifetime Automatic, Dynamic and Static Objects

  3. Arrays • double x[100]; // x[0] ... x[99] • double x[3] = {1.1, 2.2, 3.3}; • double x[] = {1.1, 2.2, 3.3}; • double m[3][3], m1[3][3], m2[3][3]; • // Code that initializes m1 and m2 ... • // m = m1 * m2 • for (int i = 0; i < 3; i++) { • for (int j = 0; j < 3; j++) { • double sum = 0.0; • for (int k = 0; k < 3; k++) { • sum += m1[i][k] * m2[k][j]; • } • m[i][j] = sum; • } • }

  4. m[0][2] m[1][1] m[1][2] m[0][1] m[1][0] m[0][0] int int int int int int 5 2 3 4 6 1 • C++ arrays use 0-origin subscripting and the elements are stored row-wise. • Warning: m[1,2] is a valid C++ expression, but it does not access a multidimensional array. • Multidimensional arrays are arrays of arrays. • int m[2][3] = { • {1,2,3}, • {4,5,6} • }; • m consists of two elements (rows), each a one-dimensional array of three elements.

  5. int* p int* p : : int j int i int i : : : int 3 int 3 int* int 4 int* Pointers • int* p; • int i = 3; • p = &i; • int j = 4; • P = &j; • *p = 5; • p = 0; • ... • if (p != 0) cout << "Pointer " << p << " points to " << *p << endl; &x address of x *p indirection, value of object pointed to by p

  6. float[5] x : Conversion x[0]: x[1]: x[2]: x[3]: x[4]: float float float float float float* Pointers and Arrays • float x[5]; Whenever x is used in an expression - except as the operand of &, sizeof or to initialize a reference - it is converted into a pointer to the first element of the array. x is of type array of float, but used as pointer to float.

  7. float[5] x : x[0]: x[1]: x[2]: x[3]: x[4]: float float float float float Conversion float* Arithmetic on Pointers • x + 2 • x points to x[0] • x+i points to x[i] • *(x+i)is equivalent to x[i] • x+i is equivalent to &x[i] • Integers can be added (or subtracted) to a pointer to an array element. • It acts as offset. The result is a pointer of the same type, which points to the element the specified number of elements away.

  8. float x[10]; • // ... initialize x ... • float* left = &x[0]; • float* right = &x[9]; • while (left < right) { • float temp = *left; • *left++ = *right; • *right-- = temp; • } • float x[10]; • float* p = &x[10]; • while (p != x) *--p = 0.0;

  9. const Pointers, Pointers to const Objects • const float pi = 3.14159; • const float* p = &pi; • pi = 2; // Compile Error • *p = 2; // Compile Error • float a, b; • float* const p1 = &a; • *p1 = 10; • p1 = &b; // Compile Error • const float e = 2.718281828; • const float* const p2 = &e; Read complex declarations from the identifier back toward the beginning of the statement. C Programmers: Do not use #define to define symbolic constants, use const for individual constants or enum for enumerations.

  10. // Create arrays with the // desired number of elements int n; cin >> n; double* const x = new double[n]; double* const y = new double[n]; // Read the data points for (int i = 0; i < n; i++) { cin >> x[i] >> y[i]; } // Accumulate sums Sx and Sy // in double precision double sx = 0.0; double sy = 0.0; for (i = 0; i < n; i++) { sx += x[i]; sy += y[i]; } // Compute coefficients double sx_over_n = sx / n; double stt = 0.0; double b = 0.0; for (i = 0; i < n; i++) { double ti = x[i] - sx_over_n; stt += ti * ti; b += ti * y[i]; } b /= stt; double a = (sy - sx * b) / n; delete [] x; delete [] y; cout << a << " " << b << endl; Runtime Array Size

  11. Pointer Operators • *p Indirection • &x Pointer to object • a[i] Array subscript • p->m Class member selection • ++p, p++ Pre(Post)increment to next element • --p, p-- Pre(Post)decrement to previous element • p+=n Increment by n elements • p-=n Decrement by n elements • p+n Offset by n elements • p-n Negative offset by n elements • new T Allocate object • new T[n] Allocate array of n objects • delete p Delete object • delete []p Delete array of objects

  12. Classes • OO Programming • Two Simple Classes • An Array Class • Class Templates • Function Templates • Exceptions • Nested Classes • Overview of C++ Programs

  13. Today • Classes • Memory Management • Classes and Functions in Detail • Inheritance

  14. Object-Oriented Programming • Object-oriented programming views a program as collection of agents, termed objects. Each object is responsible for specific tasks. • An object is an encapsulation of state (data members) and behavior (operations). • The behavior of objects is dictated by the object class. • An object will exhibit its behavior by invoking a method (similar to executing a procedure). • Objects and classes extend the concept of abstract data types by adding the notion of inheritance.

  15. Variety of Classes • Domain Classes / Data Managers / Materials Classes whose principle responsibility is to maintain data values • Data Sinks or Sources Objects that interface to data generators or consumers, but do not hold data themselves • View or Observer Classes, Tool Classes Classes that provide the graphical display of an object, but are not the object themselves • Helper Classes, Container Classes Classes that maintain little or no state information, but assist in the execution of complex tasks

  16. What Do Classes Represent • Classes that directly reflect concepts in the application domain. • Classes that are artifacts of the implementation. • User-level concepts (e.g. cars and trucks) • Generalization of user-level concepts (e.g. vehicles) • Hardware ressources (e.g. memory manager) • System ressources (e.g. output streams) • Helper classes (e.g. lists, queues, locks, ...)

  17. Two Simple Classes • Classes are programmer-defined types. • class class-name; // Declaration • class class-name { // Definition • class-body • }; • class Point { • ... • }; • Point a; // creates an object of type Point • Point square_vertices[4]; // creates an array of four Points Remember the trailing semicolon in class definitions.

  18. Mapping of Abstractions to Software real world abstractions software class Entity attribute1 ... function1() ... attributes entity behaviour

  19. CRC Cards for Class Design CRCClass-Responsibility-Collaborator Class-Name Collaborator 1 Collaborator 2 ... Responsibility 1 Responsibility 2 ....

  20. Point Line • Create from coordinates • Compute distance to another point • Compute distance to a line • Get x- and y-coordinates

  21. Line Point • Create from two points • Create from point and direction • Intersect with another line • Compute distance to a point

  22. Point definition • typedef double Number; • class Line; • class Point { • public: • Point(); // Create uninitialized • Point(Number x, Number y); // Create from (x,y) • Number distance(Point point); // Distance to another point • Number distance(Line line); // Distance to a line • Number x(); // Get x-coordinate • Number y(); // Get y-coordinate • private: • Number the_x; // x-coordinate • Number the_y; // y-coordinate • }; Class members: data members member functions

  23. Using Point Objects • #include <iostream> • using namespace std; • #include "Point.h" • int main() { • // Read the coordinates of a point and print the distance • // from the origin to the point. • Point origin(0, 0); • Number x; Point p1(1, 2); • Number y; Point* p_ptr; • cin >> x >> y; p_ptr = &origin; • Point p(x, y); cout << p_ptr->distance(p1) << e • cout << origin.distance(p) << endl; • return 0; • }

  24. Point Point origin : float 0.0 float 0.0 float the_y float the_x : : Data members of a class should be declared private to ensure that they are only accessed from within member functions. • class Point { • public: • ... • Point(Number x, Number y); • ... • private: • Number the_x; • Number the_y; • }; • Point origin(0, 0);

  25. Line definition • class Line { • public: • Line(Point p1, Point p2); • // Line through p with tangent <xDir, yDir> • Line(Point p, Number xDir, Number yDir); • Point intersect(Line line); • Number distance(Point point); • // Smallest nonparallel angle (radians) • static Number parallelism_tolerance; • private: • // ax + by + c = 0 • Number a; • Number b; • Number c; • };

  26. Using Line Objects • // Vertical line through origin • Line l1(Point(0,0), Point(0,1)); • //"anonymous" point objects are used for this line • // Line through (1,2) in direction <1,1> • Line l2(Point(1,2), 1, 1); • Point intersection; • intersection = l1.intersect(l2); • cout << "(" << intersection.x() << "," << intersection.y() • << ")" << endl;

  27. Member Function Definition • Point::Point(Number x, Number y) { • the_x = x; • the_y = y; • } • Point::Point() {} • Number Point::x() { return the_x; } • Number Point::y() { return the_y; } • Number Point::distance(Point point) { • Number x_dif = the_x - point.the_x; • //member – member of the object passed • Number y_dif = the_y - point.the_y; • return sqrt(x_dif * x_dif + y_dif * y_dif); • } • Number Point::distance(Line line) { • double result = line.distance(*this); • return result; • }

  28. Shared Objects inside Classes: static • Point Line::intersect(Line line) { • // Intersect with line. If the angle between the two lines • // is less than the parallelism_tolerance, return the point • // at infinity. The parallelism test computes the square of • // the sin of the angle. We assume that the tolerance is • // small enough for sin(theta) to be approximately equal to • //theta. • Number det = a * line.b - line.a * b; • Number sinsq = (det * det) / ( (a*a + b*b) * (line.a*line.a • + line.b*line.b) ); • if (sinsq < parallelism_tolerance * parallelism_tolerance) { • return Point(FLT_MAX, FLT_MAX); • } else { • return Point( (b * line.c - line.b * c) / det, • (c * line.a - line.c * a) / det ); • } • } • Number Line::parallelism_tolerance = .01745; // 1 degree (in rad) • Line::parallelism_tolerance = .02618; // 1.5 degrees (in radians)

  29. An Array Class: Operator Member Functions • #include <iostream> • #include "SimpleFloatArray.h" • void linefit() { • // Create arrays with the desired number of elements • int n; • std::cin >> n; • SimpleFloatArray x(n); • SimpleFloatArray y(n); • // Read the data points • for (int i = 0; i < n; i++) { • std::cin >> x[i] >> y[i]; • } • // ... same as before ... • }

  30. Runtime sizing with size given as constructor argument. • Access to element i in array x by evaluation of x[i]. • Automatic management of dynamically allocated memory associated with the array. • Automatically copy array elements when arrays are copied. • Assign one array to another, and assign one float value to every array element. • Ask array's size and resize an array dynamically.

  31. Runtime sizing with size given as constructor argument. • class SimpleFloatArray { • public: • SimpleFloatArray(int n); // Create array of n elements • SimpleFloatArray(); // Create array of 0 elements • ... • private: • int num_elts; // Number of elements • float* ptr_to_data; // Pointer to built-in array of elements • }; • SimpleFloatArray::SimpleFloatArray(int n) { • num_elts = n; • ptr_to_data = new float[n]; • } • SimpleFloatArray::SimpleFloatArray() { • num_elts = 0; • ptr_to_data = 0; • }

  32. Access to element i in array x by evaluation of x[i]. • class SimpleFloatArray { • public: • ... • float& operator[](int i); // Subscripting • ... • private: • int num_elts; // Number of elements • float* ptr_to_data; // Pointer to built-in array of elements • }; • float& SimpleFloatArray::operator[](int i) { • return ptr_to_data[i]; • }

  33. Access to element i in array x by evaluation of At(i). • class SimpleFloatArray { • public: • ... • float& At(int i); // Subscripting • ... • private: • int num_elts; // Number of elements • float* ptr_to_data; // Pointer to built-in array of elements • }; • float& SimpleFloatArray::At(int i) { • return ptr_to_data[i]; • } • SimpleFloatArray d(100); • cout << d[50] << .... cout << d.At(50),...

  34. Automatic management of dynamically allocated memory associated with the array: destructor • class SimpleFloatArray { • public: • ... • ~SimpleFloatArray(); // Destructor: destroy array • ... • private: • int num_elts; // Number of elements • float* ptr_to_data; // Pointer to built-in array of elements • }; • SimpleFloatArray::~SimpleFloatArray() { • delete [] ptr_to_data; • } When invoked with a null pointer, delete and delete [] have no effect.

  35. Automatically copy array elements when arrays are copied: copy constructor • class SimpleFloatArray { • public: • ... • SimpleFloatArray(const SimpleFloatArray&); // Copy Constructor • ... • private: • int num_elts; // Number of elements • float* ptr_to_data; // Pointer to built-in array of elements • void copy(const SimpleFloatArray& a); // Copy in elements from a • }; • SimpleFloatArray::SimpleFloatArray(const SimpleFloatArray& a) { • num_elts = a.num_elts; • ptr_to_data = new float[num_elts]; • copy(a); // Copy a's elements • }

  36. void SimpleFloatArray::copy(const SimpleFloatArray& a) { • // Copy a's elements into the elements of *this • float* p = ptr_to_data + num_elts; • float* q = a.ptr_to_data + num_elts; • while (p > ptr_to_data) *--p = *--q; • }; • or • void SimpleFloatArray::copy(const SimpleFloatArray& a) { • // Copy a's elements into the elements of *this • for(int i=0; i<num_elts; ++i) • ptr_to_data[i] = a.ptr_to_data[i]; • }

  37. Assign one array to another, and assign one float value to every array element: copy assignment operator • class SimpleFloatArray { • public: • ... • SimpleFloatArray& operator=(const SimpleFloatArray&); • ... • private: • int num_elts; // Number of elements • float* ptr_to_data; // Pointer to built-in array of elements • void copy(const SimpleFloatArray& a); // Copy in elements from a • }; • SimpleFloatArray& • SimpleFloatArray::operator=(const SimpleFloatArray& rhs) { • if ( ptr_to_data != rhs.ptr_to_data ) { • setSize( rhs.num_elts ); • copy(rhs); • } • return *this; • } Assignment should work correctly when left and right operands are the same object.

  38. Ask array's size and resize an array dynamically. • class SimpleFloatArray { • public: • ... • SimpleFloatArray& operator=(const SimpleFloatArray&); • SimpleFloatArray& operator=(float); // Scalar assignment • int numElts(); // Number of elements • void setSize(int n); // Change size • private: • int num_elts; // Number of elements • float* ptr_to_data; // Pointer to built-in array of elements • void copy(const SimpleFloatArray& a); // Copy in elements from a • };

  39. Class Templates • class SimpleFloatArray { • public: • SimpleFloatArray(int n); • SimpleFloatArray(); • SimpleFloatArray(const SimpleFloatArray&); • ~SimpleFloatArray(); • float& operator[](int i); • int numElts(); • SimpleFloatArray& operator=(const SimpleFloatArray&); • SimpleFloatArray& operator=(float); • void setSize(int n); • private: • int num_elts; • float* ptr_to_data; • void copy(const SimpleFloatArray& a); • };

  40. Class Template Definition • template<class T> • class SimpleArray { • public: • SimpleArray(int n); • SimpleArray(); • SimpleArray(const SimpleArray<T>&); • ~SimpleArray(); • T& operator[](int i); • int numElts(); • SimpleArray<T>& operator=(const SimpleArray<T>&); • SimpleArray<T>& operator=(T); • void setSize(int n); • private: • int num_elts; • T* ptr_to_data; • void copy(const SimpleArray<T>& a); • };

  41. Class Templates: Usage • #include <iostream> • #include "SimpleArray.h" • void linefit() { • // Create arrays with the desired number of elements • int n; • std::cin >> n; • SimpleArray<float> x(n); • SimpleArray<float> y(n); • // Read the data points • for (int i = 0; i < n; i++) { • std::cin >> x[i] >> y[i]; • } • // ... same as before ... • }

  42. Member function definition for class templates • void SimpleFloatArray::copy(const SimpleFloatArray& a) { • // Copy a's elements into the elements of *this • float* p = ptr_to_data + num_elts; • float* q = a.ptr_to_data + num_elts; • while (p > ptr_to_data) *--p = *--q; • } • template<class T> • void SimpleArray<T>::copy(const SimpleArray<T>& a) { • // Copy a's elements into the elements of *this • T* p = ptr_to_data + num_elts; • T* q = a.ptr_to_data + num_elts; • while (p > ptr_to_data) *--p = *--q; • }

  43. File sys.h Overview of C++ Programs • File A.h • File B.h • File main.C • #include<sys.h> • #include"A.h" • #include"B.h" • main() { • ... • } • File A.C • #include"A.h" • (Code for A) • File B.C • #include"B.h" • (Code for B) Class A Class B

  44. Object Life Cycle: Construction Allocation Preinitialization Initialization Use Destruction Cleanup Post cleanup Deallocation Object Lifetime Static Objects Automatic Objects Dynamic Objects Preventing Dangling References and Garbage Memory Management

  45. Object Lifetime • Static objects allocated once and not freed until program termination. • Automatic objects allocated when their declarations are executed and freed automatically when the block containing them terminates. • Dynamic objects allocated and freed in arbitary order under the programmers control.

  46. Class Noisy to trace object con/de struction • #include "Noisy.h" • Noisy func(Noisy n) { std::cout<< "inside func\n"; return n;} • int main() { • Noisy x("x"); • std::cout<<"\ncalling func\n"; • Noisy c = func(x); • std::cout<<"after func\n"; • std::cout << '\n'; • return 0; • }

  47. constructing: (name=x id=0) • calling func • copy construct: (name=x id=1) from: (name=x id=0) • inside func • copy construct: (name=x id=2) from: (name=x id=1) • destroying: (name=x id=1) • after func • destroying: (name=x id=2) • destroying: (name=x id=0)

  48. Noisy.h • #ifndef NOISY_H • #define NOISY_H • #include <iostream> • #include <string> • #include <sstream> • class Noisy { • static long objects_created; • long id; • std::string name; • public: • Noisy(std::string n=""): id(objects_created++), name(n) { • if (name == "") { • std::ostringstream n; • n << "obj_" << id ; • name = n.str(); • } • std::cout<<"constructing: " << *this << '\n'; • }

  49. Noisy(const Noisy& n): id(objects_created++), name(n.name) { • std::cout<<"copy constuct: " << *this << " from: " • << n << '\n'; • } • ~Noisy() {std::cout<<"destroying: " << *this << std::endl;} • Noisy& operator=(const Noisy& rhs) { • std::cout<<"assignment: " << *this << " = " << rhs << '\n'; • name = rhs.name; • return *this; • } • friend std::ostream& operator<<(std::ostream& os, const Noisy &n) { • return os << "(name=" << n.name << " id=" << n.id << ')'; • } • }; // class Noisy • long Noisy::objects_created = 0; • #endif

  50. Static Objects • are allocated once and are not freed until the program terminates. • Scope: • class scope class A { ...; static int a; ...}; A::a = 1; • file scope with external linkage extern int a; int a = 1; • file scope with internal linkage static int a; • local scope {...; static int a = 1; ...}

More Related