570 likes | 727 Vues
Christian Schulte cschulte@kth.se Software and Computer Systems School of Information and Communication Technology KTH – Royal Institute of Technology Stockholm, Sweden. C++ and C. ID1218 Lecture 09 2009-11-25. Overview. Objects Inheritance Templates Operators C.
E N D
Christian Schulte cschulte@kth.se Software andComputer Systems School of Information and Communication Technology KTH – Royal Institute of Technology Stockholm, Sweden C++ and C ID1218 Lecture 09 2009-11-25
Overview • Objects • Inheritance • Templates • Operators • C ID1218, Christian Schulte
Reading Suggestions • All of you • thorough reading of chapters 4, 6, 12 ID1218, Christian Schulte
Objects and Classes ID1218, Christian Schulte
An Integer Cell class IntCell { private: int x; public: IntCell(int y=0) { x=y; } int get() { return x; } void set(int y) { x=y; } }; ID1218, Christian Schulte
Accessors vs Mutators • Fundamental difference • set: changes object state (mutator) • get: does not change state (accessor) • In C++ accessors need to be declared const int get() const { return x; } • compiler enforces that state is not changed • well, can be controlled with const-cast… ID1218, Christian Schulte
Initializer Lists • Rewrite constructor to IntCell(int y=0) : x(y) {} • after colon: comma separated list in order of declaration of members • Old version • first initialize with default constructor for member • then assign value • New version • only initialized • Matters for non primitive data members! ID1218, Christian Schulte
Copying and Assignment • Copying is controlled by copy constructor IntCell(const IntCell& c) : x(c.x) {} • Assignment is controlled by assignment operator IntCell& operator=(const IntCell& c) { if (this != &c) x=c.x; return *this; } • These are synthesized by compiler if missing • required for resource management ID1218, Christian Schulte
A Different IntCell • Maintain integer via pointer class IntCell { private: int* x; public: IntCell(int y=0) : x(new int) { *x = y; } … } • how to manage the allocated memory? ID1218, Christian Schulte
Copy Constructor IntCell(const IntCell& c) : x(new int) { *x = *c.x; } • Used for parameter passing • Used for initialization (assume c is IntCell) IntCell d(c); ID1218, Christian Schulte
Assignment Operator IntCell& operator=(const IntCell& c) { if (this != &c) { delete x; x = c.x; } return *this; } • Returns an IntCell to allow assignment sequences a = b = c; ID1218, Christian Schulte
Destructor ~IntCell() { delete x; } • When object is deleted • by delete (for heap allocated) • by going out of scope (for automatically allocated) destructor is invoked for resource management ID1218, Christian Schulte
Default Constructor • A constructor with no arguments (or all arguments with default values) • automatically generated, if no constructors provided • Important for initialization IntCell c; invokes the default constructor ID1218, Christian Schulte
Fine Points for Objects ID1218, Christian Schulte
Friends • Grant access to class internals class ListNode { friend class IntQueue; … • Can be fine-grained: • for functions • for member functions ID1218, Christian Schulte
Static Members • Static member is part of class, not of instance • maintain data that is shared among all instances of a class • Requires declaration and definition • Declaration • use keyword static • done in header • Definition • use class name • done in implementation ID1218, Christian Schulte
Static Members: Header class Tracked { private: static int noi; public: Tracked() { noi++; … } … }; ID1218, Christian Schulte
Static Members: Implementation • Can be initialized int Tracked::noi = 0; ID1218, Christian Schulte
Namespaces • Organize multiple functions, classes, etc together • similar to Java package namespace N { class C … } ID1218, Christian Schulte
Using Namespaces • Inside the namespace, as always C • Outside namespace N::C • Convenience: make available • single class using N::C; • namespace using namespace N; • Reference to C in global namespace ::C ID1218, Christian Schulte
Incomplete Class Declaration • Mutual recursive definitions common through pointers class A { … B* data; }; class B { … A* data; }; • Use incomplete class definition class B; class A { … B* data; }; class B { … A* data; }; • only limited use of incompletely declared class allowed ID1218, Christian Schulte
Inheritance ID1218, Christian Schulte
Inheritance • Construct classes from other classes • inherit members and member functions • Supports public and private inheritance • public is normal behavior (as in Java) • Supports multiple inheritance • inherit from multiple classes • not discussed here ID1218, Christian Schulte
Person Class class Person { private: int _pn; const char* _n; public: Person(int pn, const char* n) : _pn(pn), _n(n) {} int pn() const { return _pn; } const char* name() const { return _n; } }; ID1218, Christian Schulte
Student Class class Student : public Person { private: int _pts; public: Student(int pn, const char* n, int pts) : Person(pn,n), _pts(pts) {} int pts() const { return _pts; } } ID1218, Christian Schulte
Adding Printing class Person { … void print(ostream& o = std::cout) const { o << name() << "(" << pn << ")"; } }; class Student { … void print(ostream& o = std::cout) const { Person::print(o); o << "[" << pts() << "]"; } }; ID1218, Christian Schulte
Example Persons… • Works okay Person p(1234, "Alice"); Student s(5678, "Bob", 12); p.print(); s.print(); std::cout << s.name() << std::endl; ID1218, Christian Schulte
Things Going Wrong… • Which print gets called… Student s(1234, "Carl", 34); void printme(const Person& p) { p.print(); } printme(s); • uses Person::print rather than Student::print • known as static dispatch: based on compile-time type of p ID1218, Christian Schulte
Dynamic Dispatch • Use runtime type for finding member function • default behavior in Java • in C++: mark member functions as virtual • Fix printing in base class class Person { … virtual void print(ostream& o=std::cout) const { … }; ID1218, Christian Schulte
Defaults with Inheritance • Copy constructor • invokes copy constructor on base classes • invokes copy constructor on newly added data members • Assignment operator • invokes assignment operator on base classes • invokes assignment operator on newly added data members • Destructor • invokes destructors on newly added data members • invokes destructors on base classes ID1218, Christian Schulte
Explicit Implementation class Student { … Student(const Student& s) : Person(s), _pts(s._pts) {} ~Student() { // Invokes ~Person() automatically! } Student& operator=(const Student& s) { if (this != &s) { Person::operator=(s); _pts = s._pts; } return *this; } }; ID1218, Christian Schulte
Virtual Destructor • Consider example Student* s = new Student(3456, "Deb", 2); Person* p = s; delete p; • uses static dispatch: destructor of Person! • Must declare destructor virtual in baseclass virtual ~Person() {} ID1218, Christian Schulte
Abstract Methods and Classes • Member functions can be declared abstract in base class • declare as virtual • declaration followed by = 0; • Base class for geometric shape class Shape { public: virtual double area() const = 0; … }; ID1218, Christian Schulte
A Rectangle Class class Rect : public Shape { public: … virtual double area() const { return size*size; } }; • Not longer abstract • abstract class contains at least one abstract method • only non-abstract classes allow instances! ID1218, Christian Schulte
Type Conversions • Assume we know that p is a student, really Person* p = new Student(123,"Eva",2); • Use dynamic cast Student* s = dynamic_cast<Student*>(p); • performs check and cast at runtime • returns NULL, if not a Student ID1218, Christian Schulte
Templates ID1218, Christian Schulte
Generic Programming • Common example: collections in Java • all members are of type Object • has limitations: primitive types (requires boxing), requires casts checked at runtime, … • fixed in Java 5 • Supported in C++ by templates • abstract over types and values • applicable to functions, classes, and member functions ID1218, Christian Schulte
Integer List Class class IntList { private: int h; IntList* t; public: IntList(int h0, IntList* t0) : h(h0), t(t0) {} int head() const { return h; } … }; • Does not depend on type of list elements! ID1218, Christian Schulte
Generic List Class template <typename E> class List { private: E h; List<E>* t; public: List(const E& h0, List<E>* t0) : h(h0), t(t0) {} const E& head() const { return h; } … }; ID1218, Christian Schulte
Using the Generic List Class • List of integers List<int>* il = new List<int>(4,NULL); • List of floats List<float>* fl = new List<float>(4.0,NULL); ID1218, Christian Schulte
Template Functions template <typename T> void ex(T& x, T& y) { T t = x; x = y; y = t; } • Use as follows int x = 4; int y = 5; ex(x,y); • uses automatic resolution of types • complicated process, in particular with overloading • Can be explicit ex<int>(x,y); ID1218, Christian Schulte
Compilation Model • Still most useful strategy • put everything in the header file • both declaration and definition • compiler will produce code if needed • Other strategies available • explicit instantiation in implementation template class List<int>; • export directive ID1218, Christian Schulte
Operator Overloading ID1218, Christian Schulte
Operator Overloading • Many operators (+, []) can be overloaded in C++ • useful for concise programs • Different strategies for overloading • make operator member function • make operator function • Details, see book: chapter 5 ID1218, Christian Schulte
Overloading Printing • Overload the output operator << std::ostream& operator<<(ostream& o, const Person& p) { p.print(o); return o; } ID1218, Christian Schulte
Overloading Memory Management • Memory management for class instances defined by operators static void* operator new(size_t); static void operator delete(void*); • where void* pointer to anything • where size_t integer type for specifying size • discussed later • Can be used to change memory allocation policy per class ID1218, Christian Schulte
C Programming ID1218, Christian Schulte
Major Differences… • No classes • use structs (see later) • No references • use pointers • No overloading • No templates • No default parameters • All local variable declarations must be at beginning of function • Memory management • Libraries ID1218, Christian Schulte
The Struct Type • Combine data into one structure struct IntPair { int x; int y; }; • Also available in C++, corresponds to class IntPair { public: int x; int y; }; ID1218, Christian Schulte
Preprocessor Macros • Conditional compilation • Textual substitution #define FOOVALUE 1 • Macros #define max(x,y) (x>y?x:y) • unsafe! unsafe! • things go wrong b = max(a--,c--); ID1218, Christian Schulte