Professional Documents
Culture Documents
1 June 2003
Professor, University of Nice Sophia Antipolis cole Suprieure en Sciences Informatiques (ESSI) 930 route des Colles BP 145 06903 S OPHIA A NTIPOLIS Cedex France Email : jpr@essi.fr
1 3
2 4
II
1.Introduction
Introduction C++ Characteristics
1-1
1-2 1-3
Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1-2
C and the Scandinavian School . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1-3 Origin and Influences . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1-4 Why is C++ a Difficult Language? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1-5
1-6
2-1
Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .2-2
2-3
Strong Typing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .2-3 Strong Typing... but Implicit Conversions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .2-4 Strong Typing Makes Overloading Possible . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .2-5 Different Sorts of Objects . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .2-7
2-8
Whats in a Class? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .2-8 The Natural Generalization of struct . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .2-9 A Model for Creating Instances . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2-11 A Model for Creating Instances: new and delete . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2-12 An (Abstract) Data Type . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2-16 An (Abstract) Data Type: Redefining Operators . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2-17 A Name Space . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2-18 A Name Space: Hierarchical in case of Inheritance . . . . . . . . . . . . . . . . . . . . . . . . . . 2-19 An Encapsulation Unit . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2-20 An Encapsulation Unit: Protected Members . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2-21 A Reuse Unit through Inheritance . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2-22 A Reuse Unit through Inheritance: virtual functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2-23 1996-2003 Jean-Paul R IGAULT V ERSION 3.1
III
Slides list
2-25 2-26
2-26 2-27 2-29 2-32
Copying Objects
Copy during Initialization . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Copy during Assignment . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Initialization and Assignment . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Default Copy . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Default Copy: Example . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Deep and Shallow Copy . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Value Semantics . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Preventing Copy of Objects . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
2-33
2-33 2-34 2-35 2-36 2-37 2-38 2-39 2-40
3-1
Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .3-2
Exceptions
3-3
Motivation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .3-3 Basic Mechanism . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .3-4 Basic Mechanism: Destruction of Automatic Objects . . . . . . . . . . . . . . . . . . . . . . . . . . . .3-5 Basic Mechanism: Reraising (Rethrowing) an Exception . . . . . . . . . . . . . . . . . . . . . . . . .3-6 Basic Mechanism: Uncaught Exceptions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .3-7 Exceptions Thrown from within a Constructor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .3-8 Throw List of a function . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3-11 Organization of Exceptions: catch Resolution . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3-12 Organization of Exceptions: Exceptions Hierarchy . . . . . . . . . . . . . . . . . . . . . . . . . . . 3-13 Organization of Exceptions: Class exception . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3-15 Organization of Exceptions: Naming Exceptions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3-17 Resource Acquisition is Initialization . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3-18 Termination or Resume? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3-20 Exceptions Should Remain Exceptional . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3-21
3-22
3-22 3-24 3-26 3-30 3-31
Multiple Inheritance
3-34
Reminders . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3-34 Virtual Derivation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3-35 Construction of Virtual Base Classes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3-36
IV
Slides list
3-40
3-40 3-41 3-42 3-43 3-44 3-45 3-46 3-47 3-48 3-49 3-50 3-51 3-53 3-55 3-56 3-58 3-59 3-61 3-63 3-65
3-66
3-66 3-67 3-68 3-72
3-73
3-73 3-75 3-76 3-77
3-78
3-78 3-79 3-80 3-81 3-82 3-84
References
B-1
Slides list
VI
0-1
0-2
1. Introduction
1-1
1. Introduction
Introduction
Summary C++ characteristics The object-oriented approach References
1-2
1. Introduction
C++ Characteristics
C and the Scandinavian School Scandinavian school of object-oriented programming Hybrid language Support for procedural (imperative) style Object-oriented features Compiled language Programming safety and run-time efficiency Maximal static analysis Upward compatible with (ANSI) C
1996, 2003 Jean-Paul RIGAULT Version 3.1 1-3
1. Introduction
C++ Characteristics
Origin and Influences
60 Fortran Algol 60 CPL Algol 68 BCPL C C with classes Simula 67 ML CLU ANSI C 70 80 Ada 90 Ada 95
C++
Eiffel Objective C
C++ ARM
C++ std
Smalltalk Lisp
1996, 2003 Jean-Paul RIGAULT Version 3.1
Java CLOS
1-4
1. Introduction
C++ Characteristics
Why is C++ a Difficult Language? Language mechanisms are intrinsically complex Need to master the fundamental concepts of programming languages However the language is consistent and has a clear philosophy Object-orientation is a culture Stress on architecture Need to give up centralized and purely functional reflexes and habits
1996, 2003 Jean-Paul RIGAULT Version 3.1 1-5
1. Introduction
[28] The Design and Evolution of C++ Bjarne STROUSTRUP Addison-Wesley, 1994 [13] International Standard for Information Systems Programming Language C++ ISO/IEC 14882:1998(E)
1-6
1. Introduction
[10] Design Patterns Elements of Reusable Object-Oriented Software Erich GAMMA et al. Addison-Wesley, 1995
(also available as a CD )
1996, 2003 Jean-Paul RIGAULT Version 3.1 1-7
2-1
2-2
Type of functions: prototypes (as in ANSI C) Type of an expression Can be uniquely determined from the type of its components (operands)
1996, 2003 Jean-Paul RIGAULT Version 3.1 2-3
Conversion operators
Class::operator Type() const; // Class Type
1996, 2003 Jean-Paul RIGAULT Version 3.1 2-4
(1)
2-5
(2)
The solution must be unique Impossibility and ambiguity are detected at compile-time
1996, 2003 Jean-Paul RIGAULT Version 3.1 2-6
(1)
(2)
(1)
Utilization
A *pa = new A(...);
Generated code
// allocation A *pa = (A *)operator new(sizeof(A)); // initialisation pa->A::A(...);
1996, 2003 Jean-Paul RIGAULT Version 3.1 2-12
(2)
These member-functions are static They are usable only for allocating/deallocating individual objects of class A (see further)
1996, 2003 Jean-Paul RIGAULT Version 3.1 2-13
(3)
Utilization
A *pa = new (t1, t2, ...) A(...);
(4)
Usage
A *pa = new A[n]; delete[] pa;
Objects common to all instances of the type (class static variables and member-functions)
1996, 2003 Jean-Paul RIGAULT Version 3.1 2-16
// this->first // this->last
2-18
A B1 B2 C
{ b2; C // OK // KO // KO // OK // OK
2-21
Circle rotate()
1996, 2003 Jean-Paul RIGAULT Version 3.1
Square
Figure *pf = new Circle(...); double s = pf->surface();
2-23
Objects Handling
Creation, Utilization, and Implementation Implementation Internal details Their knowledge is not needed for creating/using objects Utilization (and deletion!) Either the type of the object is known (static typing) Or dynamic typing (polymorphism) is used, and knowing a super-type of the object is enough Creation The exact type of the object must be known
1996, 2003 Jean-Paul RIGAULT Version 3.1 2-25
There is no guarantee of cleanup (destructor call) for the objects created by new
1996, 2003 Jean-Paul RIGAULT Version 3.1 2-26
(1)
All created objects have the guarantee of initialization (call to one constructor) All objects have the guarantee of cleanup (call to the destructor) except dynamically allocated ones Static objects are destroyed at the end of the program execution (exit()) Automatic objects are destroyed at the end of their block of definition Exception objects are destroyed when they are no longer needed (end of the catch clause)
1996, 2003 Jean-Paul RIGAULT Version 3.1 2-28
(1)
2-29
(2)
(3)
A
class A {private: int p; public: A(int = 0); ... }; class A1 : public A { protected: B b1; public: A1(int i = 0, int j = 1) : b1(i), A(j) {...} ... }; class A2 : public A1 {private: B b2;}; A1 a1(2, 3); A2 a2;
1996, 2003 Jean-Paul RIGAULT Version 3.1 2-31
A1
A2
Copying Objects
Copy during Initialization Copy constructor
T::T(const T&) const is optional
This constructor is invoked each time an object is created as a copy of another object of the same type Simple initialization (during definition) Passing parameters to and returning from functions by value Default copy of classes with no copy constructor(s) (see later)
1996, 2003 Jean-Paul RIGAULT Version 3.1 2-33
Copying Objects
Copy during Assignment Copy assignment operator
const T& T::operator=(const T&)
This operator is invoked each time an object is assigned to another object of the same type Simple assignment Default copy of classes with no assignment operator (see later)
2-34
Copying Objects
Initialization and Assignment An assignment is not an initialization There is exactly one initialization throughout the entire life of an object Initialization is always possible (once) whereas assignment may be forbidden (const objects) Assignment must take care of the previous state of the object whereas, for initialization, there is no such thing as a previous state An assignment trap: Beware: x = x;
1996, 2003 Jean-Paul RIGAULT Version 3.1 2-35
Copying Objects
Default Copy If a class has copy constructor(s) and/or assignment operator, these functions are entirely responsible for copying objects Otherwise, default copy is performed memberwise Each member is copied according to its own copy semantics Base class(es) are considered as members during the copy operation The memberwise procedure is applied recursively Built-in types are copied bitwise
1996, 2003 Jean-Paul RIGAULT Version 3.1 2-36
Copying Objects
Default Copy: Example
class Symbol { private: String _name; Value _val; public: // No copy constructor }; Symbol sy1(...); Symbol sy2 = sy1;
sy2._name is initialized from sy1._name, most likely by class String copy constructor If class Value has a copy constructor, this constructor is used to initialize sy2._val from sy1._val; otherwise the inside of type Value, is examined memberwise...
1996, 2003 Jean-Paul RIGAULT Version 3.1 2-37
Copying Objects
Deep and Shallow Copy Deep Copy All components are copied, recursively Shallow copy Necessary when components are shared Demand the redefinition of copy operations If sharing is used, it must be explicitly handled Memberwise copy looks like deep copy but may be in fact intermediate Everything depends on member copy semantics
1996, 2003 Jean-Paul RIGAULT Version 3.1 2-38
Copying Objects
Value Semantics A class has value semantics iff Copy operations are defined (possibly by default) Everything is as if each instance conveys its own value (lvalue/rvalue as in C) Value semantics is not incompatible with an implementation using sharing Example: class String with copy-on-write
2-39
Copying Objects
Preventing Copy of Objects To forbid copying objects for a class, make copy operations (copy constructor and copy assignment operator) private
Of course, this forbids copy only outside the class implementation A bullet-proof solution is to declare the copy operation but not to implement it: any attempt to copy will lead to a link error
class Non_Copiable { private: Non_Copiable(const Non_Copiable&); // No body definition Non_Copiable& operator=(const Non_Copiable&); // No body definition ... };
1996, 2003 Jean-Paul RIGAULT Version 3.1 2-40
3-1
3-2
Exceptions
Motivation Exceptions are mandatory because of encapsulation What can be done when an abnormal condition is detected inside a class? Notify the user Allow her to recover and resume the program at a suitable point Separate normal processing from exceptional one Respect the C++ creation/deletion semantics
setjmp/longjmp are not sufficient because local variables with destructor must be destroyed properly
1996, 2003 Jean-Paul RIGAULT Version 3.1 3-3
Exceptions
Basic Mechanism
main() {f();} void f() { try { ... g(); } catch (E1) {...}; catch (E2) {...} } void g() { try { ... h(); } catch (E1) {...} } void h() { if (...) throw E1(); else throw E2(); }
1996, 2002 Jean-Paul Rigault Version 3.1
An exception is a temporary object (of any type) When an exception is raised (thrown) the current function is exited, and the exception is propagated upward, traversing (and exiting) functions in the calling chain The propagation is stopped by the first try block with a catch for the (type of) the exception The catch clause is executed; if it does nothing special, control is then transferred after the try block (and all its catch clauses)
3-4
Exceptions
Basic Mechanism: Destruction of Automatic Objects
void f() { try { ... g(); } catch (E1) {...}; } void g() { String s("hello"); h(); ... } void h() { String s1("salut"); ... if (...) throw E1(); }
1996, 2002 Jean-Paul Rigault Version 3.1
If a function is traversed by a propagated exception, all automatic (local) objects are properly destroyed (i.e., their destructor gets invoked)
deletion of s
Nothing similar happens for dynamically allocated objects (allocated by new) Thus it is the programmers responsibility to provoke the destruction of dynamically allocated objects (see later)
3-5
deletion of s1
Exceptions
Basic Mechanism: Reraising (Rethrowing) an Exception
main() {f();} void f() { try { ... g(); } catch (E1) {...}; } void g() { try { ... h(); } catch (E1) {...; throw;} } void h() { if (...) throw E1(); }
In a catch clause, using throw without parameter simply repropagates the current exception upwards
3-6
Exceptions
Basic Mechanism: Uncaught Exceptions If no try block in the calling chain has a catch clause for the current exception, the standard function terminate() is called By default, terminate() simply calls abort() But the user may provide her own version
3-7
Exceptions
Exceptions Thrown from within a Constructor (1)
All members fully constructed before the exception is thrown are deleted The destructors of fully constructed components are correctly called Partially constructed sub-objects are not destructed It is indispensable to understand clearly in which order constructions/deletions are performed It is not a good idea to throw an exception from within a destructor!
1996, 2003 Jean-Paul RIGAULT Version 3.1 3-8
Exceptions
Exceptions Thrown from within a Constructor
class A1 { String id; public: A1(const String& s) : id(s) {} }; class A2 { int val; public: A2(int v) {if (v==0) throw Invalid();} }; class B : public A1, public A2 { String name; public: B(const String& s, int v) : A1(s), A2(v) {name = s; throw Exception_B();} };
(2)
Exceptions
Exceptions Thrown from within a Constructor Function try block
void f() try { function-body } catch (E1) { ... } catch (E2) { ... } ...
(3)
Exceptions
Throw List of a function It is possible to specify the list of exceptions that a (member or regular) function may throw
void f() throw (E1, E2); void g() throw (); // no exception void h(); // any exception
C++ only requires a dynamic check Static checking is possible but delicate If an exception forbidden by the throw list is thrown, unexpected() is called (and by default abort())
1996, 2003 Jean-Paul RIGAULT Version 3.1 3-11
Exceptions
Organization of Exceptions: catch Resolution For a same try block, catch clauses are scanned from top to bottom Type conformance must be exact, except that standard conversions related to inheritance (only) are authorized The temporary object created by throw may be retrieved in catch, by value but also by reference
catch (Stack::exception& e) {...} Above, dynamic typing may be honored for e
Exceptions
Organization of Exceptions: Exceptions Hierarchy
exception
(1)
system_err
arithmetic_err
IO_err
zero_divide
overflow
underflow
file_err
network_err
network_file_err
1996, 2003 Jean-Paul RIGAULT Version 3.1
Exceptions
Organization of Exceptions: Exceptions Hierarchy (2)
try { ... } catch (overflow& ov) {...} catch (arithmetic_err& e) {cout << e.what();} catch (file_err) {...} catch (IO_err) {...} catch (...) {cout << "unexpected exception";} Be careful with catch order!
3-14
Exceptions
Organization of Exceptions: Class exception Defined in the ANSI standard
class exception { public: exception() throw (); exception(const exception&) throw (); exception& operator=(const exception&) throw (); virtual ~exception() throw (); virtual const char *what() const throw (); };
(1)
3-15
Exceptions
Organization of Exceptions: Class exception (2)
exception
logic_err
runtime_err
domain_error
invalid_argument out_of_range
length_error
overflow_error
range_error
3-16
Exceptions
Organization of Exceptions: Naming Exceptions
class Stack { public: class All : public My_Lib_Except {...}; class Full : public All {...}; class Empty : public All {...}; ... }; try { ...; st.push(v); ... } catch (Stack::Full) {...} catch (Stack::All) {...}
3-17
Exceptions
Resource Acquisition is Initialization
void f1() { FILE *fp = fopen("toto", "w"); ... fclose(fp); } void f2() { String *ps = new String("hello"); ... delete ps; } void f3() { Sema.P(); ... Sema.V(); }
1996, 2002 Jean-Paul Rigault Version 3.1
(1)
Who is going to call fclose if an exception traverses this function? Who is going to delete ps if an exception traverses this function? Who is going to release the semaphore (Sema.V()) if an exception traverses this function?
3-18
Exceptions
Resource Acquisition is Initialization
class My_File { FILE *fp; public: My_File(...) {fp = fopen(...);} ~My_File() {fclose(fp);} }; class Handle { String *ps; public: Handle(...) {ps = new String(...);} ~Handle() {delete ps;} }; class Lock { Semaphore& sema; public: Lock(Semaphore& s) : sema(s) {sema.P();} ~Lock() {sema.V();} };
1996, 2002 Jean-Paul Rigault Version 3.1
(2)
void f1() { My_File mf("toto", "r"); ... // No more need to call fclose() } void f2() { Handle h("hello"); ... // No more need to delete the String } void f3() { Lock l(Sema); ... // No more need to free the semaphore }
3-19
Exceptions
Termination or Resume? C++ exceptions are propagated upward the calling chain Moreover if the catch clause itself does not contain a transfer instruction, control resumes at the end of the try block where the exception was caught
The end of the try block means after the last catch clause of the block
Therefore it is impossible to resume execution where the exception was thrown (i.e. just after throw) Everything is as if the calling chain had been lost
1996, 2003 Jean-Paul RIGAULT Version 3.1 3-20
Exceptions
Exceptions Should Remain Exceptional Exceptions should be reserved to exceptional situations! This is largely a matter of context
while ((c = getchar()) != EOF) {...}
Above something to read was normally expected; indeed, here the end of file is exceptional
1996, 2003 Jean-Paul RIGAULT Version 3.1 3-21
(1)
3-22
Run Time Type Information has not to be built-in, since we have already virtual functions However it is more comfortable and safer to delegate its implementation to the compiler Generally the RTTI mechanism is only relevant when accessing objects through pointers or references In other cases, static typing is performed
3-23
(1)
Return 0 if p does not point to an object of type T or (publicly) derived from T; otherwise return the cast result Use with a reference r
T& rt = dynamic_cast<T&>(r);
Throw exception bad_cast if r does not reference an object of type T or (publicly) derived from T Require that T be a polymorphic type
1996, 2003 Jean-Paul RIGAULT Version 3.1 3-24
(2)
Figure *pf1 = new Circle(c0, R); Figure *pf2 = new Ellipse(c1, A, B); Ellipse *pe; Circle *pc; x = pf1->a_axis();// NO pe = dynamic_cast<Ellipse *>(pf1); // pe != 0 x = pe->a_axis();// YES... now pc = dynamic_cast<Circle *>(pf2); // pc == 0 pc = dynamic_cast<Circle *>(pf1); // pc != 0 char *p = dynamic_cast<char*>(pf1); // does not compile since char is // not polymorphic
3-25
Once dynamic_cast built into the language, the path is short to dynamic type identification A type descriptor (an instance of the predefined class type_info) is associated with each type (and thus with each class) Operator typeid returns a reference to the type descriptor of its parameter
const type_info& typeid(type-name); const type_info& typeid(expression);
3-26
(2)
3-27
(3)
3-28
(4)
3-29
(1)
(2)
T1 and T2 may have any pointer type or, more generally, any integral type This cast is intrinsically unsafe
it respects const (this is almost its only guarantee!) No adjustment of the value returned in case of multiple inheritance (contrarily to static_cast) The only sensible use is as a conversion relay (convert into some type, then backward to the original type)
1996, 2003 Jean-Paul RIGAULT Version 3.1 3-32
The target type must be the original type but without const or volatile If the object is actually constant or actually volatile, the result is undefined!
1996, 2003 Jean-Paul RIGAULT Version 3.1 3-33
Multiple Inheritance
Reminders The same class cannot appear several times as a direct base class The inheritance graph must be acyclic (DAG) Ambiguities are detected at compile time (provided that they are effective) and must be statically resolved If a class appears as a base class through several inheritance paths, the default is to have (in the derived class) as many copies of the base class as there are inheritance paths If only one copy is suitable, use virtual derivation
1996, 2003 Jean-Paul RIGAULT Version 3.1 3-34
Multiple Inheritance
Virtual Derivation
class Vehicule { public: virtual double speed() const; ... }; // Suppose the following two classes // do not redefine speed() class Plane : virtual public Vehicule {...}; class Boat : virtual public Vehicule {...}; class Sea_Plane : public Plane, public Boat {...}; Sea_plane sp(...); v = sp.speed(); // No ambiguity here
1996, 2003 Jean-Paul RIGAULT Version 3.1 3-35
Multiple Inheritance
Construction of Virtual Base Classes (1)
Virtual base classes must be constructed exactly once (as any C++ object) They are constructed before any regular base class Thus they must Either be constructible by default Or be (explicitly) constructed by any (concrete) derivative, whatever how deep this derivative is in the hierarchy
3-36
Multiple Inheritance
Construction of Virtual Base Classes
class A { public: A(int); // no default construction }; class B : virtual public A {...}; class C : public B { public: C(int i): A(i), B(...) {...}// C must construct its base A }; class D: public C{ public: // D must also construct A : D(int i): A(i), C(i){...} // the usual construction // relay does not work! };
1996, 2003 Jean-Paul RIGAULT Version 3.1 3-37
(2)
Multiple Inheritance
Conversions and Virtual Base Classes
class class class class A {...}; B1 : public virtual A {...}; B2 : public virtual A {...}; C : public B1, public B2 {...};
(1)
A* B1* B2* C* B2
class A
B1
B2
Just a principle outline
C
1996, 2003 Jean-Paul RIGAULT Version 3.1
3-38
Multiple Inheritance
Conversions and Virtual Base Classes (2)
The complexity of conversions and addressing explains why virtual derivation is not the default in C++ Note that pointers to members take into account this complexity Operator dynamic_cast makes downward cast possible for virtual base classes
static_cast does not give a correct result in case of virtual inheritance
3-39
3-40
T denotes here any C++ type (class or built-in)... ... as long as the type has operator < and a copy constructor (possibly defined by default)
1996, 2003 Jean-Paul RIGAULT Version 3.1 3-41
3-42
There may remain only lexical and syntactic uses of the preprocessor
1996, 2003 Jean-Paul RIGAULT Version 3.1 3-44
template <typename Elem, int N> class Fixed_Array { Elem tab[N]; ... };
1996, 2003 Jean-Paul RIGAULT Version 3.1 3-45
3-46
3-47
3-50
(1)
(2)
3-52
(1)
template <typename T, void (*SORT)(T, T[])> class Sortable {...}; void sort(int, int[]); Sortable<int, sort> s(...); template <typename T = int, int N = 10> class Fixed_Array {...};
template <typename U, template <typename T> class Container = list> class Something {...}; ... Something<int, vector> sth;
1996, 2003 Jean-Paul RIGAULT Version 3.1 3-54
(1)
(2)
(1)
3-60
(1)
In which object-file (.o) must the compiler generate the corresponding binary code? Generate static functions in the current compilation unit?
the code for the same template instance will be duplicated in several compilation units
Generate template code by demand in some repository and use a pre-link processor? Generate special code in the current compilation unit and rely on smart linker to collapse duplicated code? Rely on explicit template instantiation?
1996, 2003 Jean-Paul RIGAULT Version 3.1 3-62
(1)
(2)
CC (compiler)
Source generation
Source-files (template)
CC (compiler)
Object-files (template)
3-64
3-66
Legend:
already in ANSI C introduced in C++ (3.0) introduced by ANSI C++ introduced by ANSI C++ as an alternative denotation for some operators (same sort of brain damage as trigraphs!)
3-67
(1)
(2)
// OK // OK
3-69
(3)
// OK: redefines f
3-70
(4)
3-71
(1)
(2)
3-74
Through a pointer
void Window::repeat(void (Window::*op)(), int n) { for (int i = 0; i < n; ++i) (this->*op)(); }
int A::*pmi = &A::x; A a, *pa = &a; ... a.*pmi = 12; // a.x = 12 pmi = &A::y; pa->*pmi = 27: // pa->y = 17
Note that this conversion goes into the direction opposite to the other inheritance conversions
1996, 2003 Jean-Paul RIGAULT Version 3.1 3-77
3-78
A namespace is open : it can be extended simply by opening a new namespace clause with the same name The anonymous namespace is guaranteed collision-free Name spaces can be nested
1996, 2003 Jean-Paul RIGAULT Version 3.1 3-79
using namespace My_Lib; // using directive List l; f(3, 12.5); int i = f('a');
1996, 2003 Jean-Paul RIGAULT Version 3.1 3-80
3-81
Standard ISO C++ library are in a predefined name space (std) Standard ANSI C .h files are also part of ISO C++, but their name is prefixed by c (e.g., <cstdio.h>, <cstring.h>, <cctypes.h>...) All standard ANSI C functions are part of the std namespace (prinft, sin...)
3-82
(2)
3-84
(2)
3-85
References
[1]
Andrei ALEXANDRESCU Modern C++ Design: Generic Programming and Design Patterns Applied
[6]
Adison-Wesley, 2000
Make C++ run fast, avoid the inefficiency pitfalls.
B-1
Bibliographie commente
ISO/IEC 14882:1998(E)
The standard itself. Not really a tutorial! [14] Nicolai M. JOSUTTIS The C++ Standard Library [21]
B-2
Bibliographie commente
in Research Directions in Object-Oriented Programming, pp 479-560, Bruce Shiver et Peter Wegner (diteurs), The MIT Press, 1988.
An attempt to model the object-oriented concepts by a prestigious author. Always instructive.
B-3