
CS 242 History C++ C++ is an object-oriented extension of C C was designed by Dennis Ritchie at Bell Labs • used to write Unix, based on BCPL C++ designed by Bjarne Stroustrup at Bell Labs John Mitchell • His original interest at Bell was research on simulation • Early extensions to C are based primarily on Simula • Called “C with classes” in early 1980’s • Popularity increased in late 1980’s and early 1990’s • Features were added incrementally Classes, templates, exceptions, multiple inheritance, type tests... Reading: Chapter 12 Design Goals How successful? Provide object-oriented features in C-based Given the design goals and constraints, language, without compromising efficiency • this is a very well-designed language • Backwards compatibility with C Many users -- tremendous popular success • Better static type checking However, very complicated design • Data abstraction • Many features with complex interactions • Objects and classes • Difficult to predict from basic principles • Prefer efficiency of compiled code where possible • Most serious users chose subset of language – Full language is complex and unpredictable Important principle • Many implementation-dependent properties • If you do not use a feature, your compiled code • Language for adventure game fans should be as efficient as if the language did not include the feature. (compare to Smalltalk) Significant constraints Overview of C++ C has specific machine model Additions and changes not related to objects • Access to underlying architecture • type bool No garbage collection • pass-by-reference • Consistent with ggyoal of efficiency • user-defined overloading • Need to manage object memory explicitly • function templates Local variables stored in activation records • … • Objects treated as generalization of structs – Objects may be allocated on stack and treated as L-values – Stack/heap difference is visible to programmer 1 C++ Object System Some good decisions Object-oriented features Public, private, protected levels of visibility • Classes • Public: visible everywhere • Objects, with dynamic lookup of virtual functions • Protected: within class and subclass declarations • Inheritance • Private: visible only in class where declared – Single and multiple inheritance Friend functions and classes – Public and private base classes • Careful attention to visibility and data abstraction • Subtyping – Tied to inheritance mechanism Allow inheritance without subtyping • Encapsulation • Better control of subtyping than without private base classes Some problem areas Sample class: one-dimen. points Casts class Pt { • Sometimes no-op, sometimes not (e.g., multiple inheritance) public: Lack of garbage collection Pt(int xv); • Memory management is error prone Overloaded constructor – Constructors, destructors are helpful though Pt(Pt* pv); Objects allocated on stack int getX(); Public read access to private data • Better efficiency, interaction with exceptions virtual void move(int dx); Virtual function • BUT assignment works badly, possible dangling ptrs protected: Overloading void setX(int xv); Protected write access • Too many code selection mechanisms? private: Multiple inheritance int x; Private member data • Efforts at efficiency lead to complicated behavior }; Virtual functions Sample derived class Member functions are either class ColorPt: public Pt { Public base class gives supertype • Virtual, if explicitly declared or inherited as virtual public: ColorPt(int xv,int cv); • Non-virtual otherwise ColorPt(Pt* pv,int cv); Overloaded constructor Virtual functions ColorPt(ColorPt* cp); • Accessed by indirection through ptr in object int getColor(); Non-virtual function • May be redefined in derived (sub) classes virtual void move(int dx); Virtual functions Non-virtual functions virtual void darken(int tint); • Are called in the usual way. Just ordinary functions. protected: • Cannot redefine in derived classes (except overloading) void setColor(int cv); Protected write access private: Pay overhead only if you use virtual functions int color; Private member data }; 2 Run-time representation Compare to Smalltalk Point object Point vtable Code for move Point object Point class Template Method dictionary vptr x newX:Y: x 3 2 y ... ... 3 move ColorPoint object ColorPoint vtable Code for move ColorPoint class Template vptr ColorPoint object Method dictionary x 5 x c blue Code for darken 4 y newX:Y:C: 5 color color move red Data at same offset Function pointers at same offset Why is C++ lookup simpler? Looking up methods Smalltalk has no static type system Point object Point vtable Code for move • Code p message:pars could refer to any object vptr • Need to find method using pointer from object x 3 • Different classes will put methods at different place in method dictionary ColorPoint object ColorPoint vtable Code for move C++ type gives compiler some superclass vptr • Offset of data, fctn ptr same in subclass and superclass x 5 Code for darken • Offset of data and function ptr known at compile time c blue • Code p->move(x) compiles to equivalent of Point p = new Pt(3); (*(p->vptr[1]))(p,x) if move is first function in vtable p->move(2); // (*(p->vptr[0]))(p,2) data passed to member function; see next slides Looking up methods, part 2 Calls to virtual functions Point object Point vtable Code for move One member function may call another vptr class A { x 3 public: virtual int f (int x); virtual int g(int y); ColorPoint object ColorPoint vtable Code for move }; vptr darken() int A::f(int x) { … g(i) …;} x 5 int A::g(int y) { … f(j) …;} Code for darken c blue How does body of f call the right g? • If g is redefined in derived class B, then inherited f Point cp = new ColorPt(5,blue); must call B::g cp->move(2); // (*(cp->vptr[0]))(cp,2) 3 “This” pointer (analogous to self in Smalltalk) Non-virtual functions Code is compiled so that member function takes How is code for non-virtual function found? “object itself” as first argument Same way as ordinary “non-member” functions: Code int A::f(int x) { … g(i) …;} • Compiler generates function code and assigns address compiled as int A::f(A *this, int x) { … this->g(i) …;} • Address of code is ppylaced in symbol table • At call site, address is taken from symbol table and “this” pointer may be used in member function placed in compiled code • Can be used to return pointer to object itself, pass • But some special scoping rules for classes pointer to object itself to another function, ... Overloading • Remember: overloading is resolved at compile time • This is different from run-time lookup of virtual function Scope rules in C++ Virtual vs Overloaded Functions Scope qualifiers class parent { public: • binary :: operator, ->, and . void printclass() {printf("p ");}; virtual void printvirtual() {printf("p ");}; }; • class::member, ptr->member, object.member class child : public parent { public: A name outside a function or class, void printclass() {printf( "c ");}; • not prefixed by unary :: and not qualified refers to virtual void printvirtual() {printf("c ");}; }; global object, function, enumerator or type. main() { A name after X::, ptr-> or obj. parent p; child c; parent *q; • where we assume ptr is pointer to class X and obj is p.printclass(); p.printvirtual(); c.printclass(); c.printvirtual(); an object of class X q = &p; q->printclass(); q->printvirtual(); • refers to a member of class X or a base class of X q = &c; q->printclass(); q->printvirtual(); } Output: p p c c p p ? ? Virtual vs Overloaded Functions Subtyping class parent { public: Subtyping in principle void printclass() {printf("p ");}; • A <: B if every A object can be used without type virtual void printvirtual() {printf("p ");}; }; error whenever a B object is required class child : public parent { public: • Example: void printclass() {printf( "c ");}; Point: int getX(); Public members virtual void printvirtual() {printf("c ");}; }; void move(int); main() { ColorPoint: int getX(); parent p; child c; parent *q; int getColor(); Public members p.printclass(); p.printvirtual(); c.printclass(); c.printvirtual(); void move(int); q = &p; q->printclass(); q->printvirtual(); void darken(int tint); q = &c; q->printclass(); q->printvirtual(); C++: A <: B if class A has public base class B } • This is weaker than necessary Why? Output: p p c c p p p c 4 Independent classes not subtypes Why C++ design? class Point { class ColorPoint { Client code depends only on public interface public: public: • In principle, if ColorPoint interface contains Point int getX(); int getX(); void move(int); interface, then any client could use ColorPoint in void move(int); place of point pprotected:rotected: ... int getColor(); void darken(int); • However -- offse t in v ir tua l func tion ta ble may differ private: ... protected: ... }; • Lose implementation efficiency (like Smalltalk) private: ... Without link to inheritance }; • subtyping leads to loss of implementation efficiency C++ does not treat ColorPoint <: Point as written Also encapsulation issue: • Need public inheritance ColorPoint : public Point • Subtyping based on inheritance is preserved under • Why?? modifications to base class … Function subtyping Examples Subtyping principle If circle <: shape, then • A <: B if an A expression can be safely used in any context where a B expression is required circle → shape Subtyping for function results • If A <: B , then C → A<:CA <: C → B Subtyping for function arguments circle → circle shape → shape • If A <: B, then B → C <: A → C Terminology shape → circle • Covariance: A <: B
Details
-
File Typepdf
-
Upload Time-
-
Content LanguagesEnglish
-
Upload UserAnonymous/Not logged-in
-
File Pages7 Page
-
File Size-