Beruflich Dokumente
Kultur Dokumente
1.
2.
3.
4.
Advanced C++
Introduction
Basic C++ mechanisms
Advanced C++ mechanisms
The Standard Template Library
Jean-Paul Rigault
Polytechnic Engineering School, University of Nice
Computer Science Department
Email: jpr@polytech.unice.fr
13/06/09 15:52
13/06/09 15:52
Introduction
Summary
Advanced C++
Characteristics of C++
Some references
1. Introduction
13/06/09 15:55
1-1
1970
1980
Fortran
Algol 60
Compiled language
1960
1990
2000
Hybrid language
1-2
Characteristics of C++
Origin and influences
Characteristics of C++
13/06/09 15:55
CPL
Ada 83
Algol 68
BCPL
Ansi C
C with
classes
Simula 67
ML
C++
1-3
13/06/09 15:55
Std C++
Eiffel
Java
Smalltalk
13/06/09 15:55
C++ arm
CLU
Objective C
Lisp
Ada 95
CLOS
2005-2006 Jean-Paul Rigault
1-4
Characteristics of C++
Why is C++ difficult?
Some references
Stress on architecture
Need to revisit centralized and purely functional reflexes
13/06/09 15:55
Object-orientation is a culture
Some references
1-5
(1)
13/06/09 15:55
1-6
(2)
C++ Templates
The Complete Guide
David Vandevoorde and Nicolai Josuttis
Addison Wesley, 2003
Effective C++ CD
85 Specific Ways to Improve your Program Design
Scott Meyers, 2000
Effective STL
50 Specific Ways to Improve your Use of the Standard Template Library
Scott Meyers, 2001
Modern C++ Design
Generic programming and Design Patterns Applied
Andre Alexandrescu, 2001
13/06/09 15:55
1-7
Advanced C++
13/06/09 15:56
2-1
13/06/09 15:56
Scalar types
(1)
Instance
int i, j;
string s1("hello");
13/06/09 15:56
2-2
Built-in types
Integral types: char, int and their variations, pointers
Real types: float, double and their variations
Enumerations (user defined)
These are also integral types
2-3
13/06/09 15:56
2-4
(2)
Pointer
Reference
ri = 12;
// modify the object (i)
int j = 10;
int& rj = j;
ri = rj;
// set the value of ri (or i) to be
// the one of rj (or j), that is 10
13/06/09 15:56
2-5
2-6
(5)
13/06/09 15:56
13/06/09 15:56
(4)
(3)
2-7
13/06/09 15:56
2-8
(1)
(2)
Type declaration
Variables
int i;
string str = "hello";
13/06/09 15:56
2-9
Standard conversions
x = (a + b) * 2 + c
Tx
Ta
Tb
int Tc
converted into
T(a+ b) * 2
2-10
Implicit conversion
Ta + b
(3)
13/06/09 15:56
T(a+ b) * 2 + c
13/06/09 15:56
2-11
13/06/09 15:56
2-12
2-13
13/06/09 15:56
13/06/09 15:56
(2)
Distinguishing two functions only from their return value type would
break the rule that says that the type of an expression is uniquely
determined from the type of its operands
int f();
double f();
int x = f();// which is the type of expression f()?
13/06/09
15:56
Beware
Overloading
(1)
Candidate functions
All functions visible at the
point of call and bearing the
same name as the one that is
called
Include possible instances of
function templates if their
argument deduction
succeeds
Relies on name lookup
2-14
(3)
Viable functions
All candidate functions that
can be considered for the call
Functions should have
adequate number of
arguments
There should exist
conversions between each
call argument and the
corresponding parameter of a
viable function
2-15
13/06/09 15:56
2-16
Identity
Lvalue transformations
Lvalue to rvalue
Array to pointer
Function to pointer
Qualification adjustment
13/06/09 15:56
(4)
3. Other conversions
Integral conversions
Floating-integral conversions
2. Promotion
Integral promotions
include inheritance
conversions
Boolean conversions
4. User defined conversions
Cast operators
void f(double&);
double x;
f(x);
// OK
f(3.14);
// NO
void g(const double&);
g(3.14);
// OK
class A {];
class B : public A {};
void f(A&);
B b;
f(b);
// OK
float to double
2005-2006 Jean-Paul Rigault
2-17
13/06/09 15:56
1. Lvalue transformation
2. Promotion or other conversion (promotion is better)
3. Qualification conversion
2-19
2-18
(7)
(6)
13/06/09 15:56
(5)
std conv. seq. < user-def. conv. seq. < ellipsis conv. seq.
exact match < promotion < other conversions
13/06/09 15:56
2-20
void
void
void
void
void
void
(8)
int i;
const int *pci = &i;
int *pi = &i;
const string sc = "hello";
string s;
C programmer
OO programmer/modeler
f(pci);
// f(const int *)
f(pi); // f(int *)
g(sc);
// g(const
string&)
g(s);
// g(string&)
Software engineer
// ambiguous
13/06/09 15:56
2-21
A name space
An encapsulation unit
A reuse unit
13/06/09 15:56
2-22
2-23
Member-functions
Access control
Initialization/finalization operations
Inheritance
Software engineer
OO programmer/modeler
A name space
An encapsulation unit
A reuse unit
C programmer
13/06/09 15:56
h(s);
13/06/09 15:56
2-24
A struct can have constructors, destructors, memberfunctions, access control labels, etc.
Default access control for members is public for struct (its
private for class)
Default access control for derivation is public for struct
(its private for class)
struct MyStruct : AnotherStruct { // public
string s;
// public
private:
int n;
// private, of course
};
13/06/09 15:56
2-25
13/06/09 15:56
Where?
Object creation
Lifetime
2.Returning memory
13/06/09 15:56
2-27
Scope
Block
automatic deletion
Block
Statically
allocated objects
Data
segment
Whole program
execution
automatic deletion
Block (static)
Class (static)
File (static)
Program (extern)
Dynamically
allocated objects
Heap
Scope of the
pointers that give
access to them
Exception objects
Heap?
Catch clauses
Object deletion
2-26
4 different ways
1. Allocating memory
13/06/09 15:56
2-28
// File f2.cpp
extern string *f();
int glob = 12;
string *f() {
double x;
static int st = 10;
if () throw Exc();
return new string();
void g() {
try {
string *ps = f();
// ...
delete ps;
}
catch (Exc& e) {
cout << e.what() << endl;
}
automatically allocated
statically allocated
dynamically allocated
thrown (exception)
13/06/09 15:56
2-29
13/06/09 15:56
Per class
13/06/09 15:56
Override
Overload
For an array
For an array
For an array
For an array
2-30
Globally
Prototypes
void *operator new(size_t);
void operator delete(void *);
13/06/09 15:56
2-32
Prototypes
class A {
public:
void *operator new(size_t);
void operator delete(void *);
// ...
};
2-33
13/06/09 15:56
#include <new>
void *operator new(size_t, void *);
char buff[1000];
A *pa = new (buff) A();
13/06/09 15:56
2-34
13/06/09 15:56
Usage
A *pa = new A[n];
delete[] pa;
individual instances of A
individual instances of any class derived from A (that does not
define its own version of these operators)
2-35
13/06/09 15:56
2-36
13/06/09 15:56
2-37
class A {
private:
A() {}
};
class C : public A {
private:
B _b;
};
class B {
public:
B(int);
};
C::C()
: A(), _b() // impossible!
{}
13/06/09 15:56
2-39
2-38
C++ does not define any order for static initialization across
several compilation units
13/06/09 15:56
C++ does not define any order for static destruction across
several compilation units
13/06/09 15:56
2-40
10
3. Constructor body
13/06/09 15:56
2-41
Attention! DANGER !
2-42
class A1 : public A {
protected: B _b1;
public:
A1(int i = 0, int j = 1)
: _b1(i), A(j) {...}
// ...
};
13/06/09 15:56
A1
_b1
B
_b2
A2
2-43
A1 a1(2, 3);
13/06/09 15:56
2-44
11
A2:A2()
: A1(),
_b2()
{}
default default
constructor
2-45
2-47
2-46
(1)
// File A.cpp
string A::st("hello");
// ...
13/06/09 15:56
// File A.h
class A {
private:
static string st;
// ...
};
13/06/09 15:56
that is for integral types (char, int and all their variations, and
pointers) and real types (float and double)
int g; // initialization at load time (0)
void f() {
int a = int();
// a initialized to 0
int b; // b not initialized by default!!
int *p1 = new int;// *p1 not initialized by default!!
int *p2 = new int();
// *p2 initialized to 0
int *p3 = new int(14); // *p2 initialized to 14
}
no constructor!
13/06/09 15:56
class A1 : public A {
protected: B _b1;
public:
A1(int i = 0, int j = 1)
: b1(i), A(j) {...}
...
};
13/06/09 15:56
Static definition
Initialization (constructor call)
2-48
12
(2)
// file A.h
// file B.h
class A {
public:
static int _ist;
class B {
private:
static B _bst1;
static B _bst2;
public:
B(int);
};
};
// file A.cpp
#include "A.h"
13/06/09 15:56
// file B.cpp
#include "B.h"
#include "A.h"
B B::_bst1(A::_ist);
B B::_bst2(A::fst());
// ...
2-49
A::A(const A&);
Invoked by default each time an instance of A is initialized from
another instance of A
Simple initialization
Passing parameters and returning from functions by value
Default copy of classes with no copy constructor (see later)
13/06/09 15:56
2-50
(2)
Copy constructor
(1)
sizeof ::
.*
?:
13/06/09 15:56
A a1();
A a2 = a1;
Preprocessor operators: #
##
Compile-time operators: typeid
The three following operators: .
// ??
// OK
2-51
Simple assignment
Default copy of classes with no copy assignment operator
(see later)
13/06/09 15:56
2-52
13
(3)
An assignment trap:
class B : public A {
int i;
char *pc;
string s;
// no copy operations
};
B b1();
B b2 = b1;
b1 = b2;
2-53
2-54
(3)
2-55
13/06/09 15:56
(2)
B::B(const B& b)
: A((A&)b),
i(b.i), pc(b.pc), s(b.s)
{}
13/06/09 15:56
13/06/09 15:56
(1)
// const member
// reference data member
// private copy constructor
13/06/09 15:56
2-56
14
2-57
13/06/09 15:56
2-58
(2)
class A {
class B { };
B m(B);
friend void f(B);
// ...
};
// List::nb_lists
// List::N1, List::N2
// List::Cell
A::B A::m(B b) {
B b1;
// ...
}
// this->first
// this->last
void f(A::B b) {
A::B b2;
// ...
}
// List::fst()
// this->List::method()
13/06/09 15:56
private:
Non_Copiable(const Non_Copiable&);
Non_Copiable& operator=(const Non_Copiable&);
// No definition (no body) for these operations
public:
Non_Copiable() {}
};
class List {
private:
static int nb_lists;
enum {N1, N2};
class Cell {
int info;
Cell *next;
// ...
};
Cell *first;
Cell *last;
public:
static void fst();
void method();
// ...
};
class Non_Copiable {
13/06/09 15:56
2-59
13/06/09 15:56
2-60
15
Name lookup
This is the
simple case
See also
namespaces
further
identifier to lookup
13/06/09 15:56
... id ...
2-61
2-63
2-62
Class scope
Body of friend functions
Class scope of friend classes
13/06/09 15:56
void C::f(double n) {
k = 0;
// this-> k, C::k
n = 3.14;
// function parameter
j = 2;
// B::j, but not
// accessible here
i = 3; // A::i
i = ::i;
// ::i is global i
}
13/06/09 15:56
2-64
16
B b;
f(b); // forbidden
13/06/09 15:56
2-65
Friend function
A function that is not a
member of the class
But that has access to the
class private and protected
members
Friend class
All the friend class member
functions are friend of the first
class
Restriction on friendship
Not symmetric
Not inherited
Not transitive
13/06/09 15:56
(1)
2-67
B2
C
b2.prot = 4;
// OK : b2 is a B2 !
c.prot = 5;
// OK : conversion C B2
// (a C is a B2)
a.prot = 2;
// KO : no conversion A
B2
b1.prot = 3;
// KO : no conversion B1
B2
2005-2006 Jean-Paul Rigault
13/06/09
15:56
}
protected is not
really intermediate
between public and
private!
2-66
It is impossible to impose a
friend to a class
B1
void f(A a) {
A a1;
a1._priv = a._priv;
}
13/06/09 15:56
(2)
class B {
friend void g();
private:
int _i;
public:
void m(A a) {
A a1;
a1._priv = a._priv;
}
};
void g() {
A a;
_i = a._priv;
}
// NO
2-68
17
Ellipse
surface()
Rectangle
surface()
Circle
Square
rotate()
13/06/09 15:56
2-69
13/06/09 15:56
Abstract class
Concrete class
class Figure {
public:
// pure virtual:
// class is abstract
virtual
double surface() const = 0;
// virtual, but not pure
// virtual
virtual void rotate();
};
13/06/09 15:56
2-70
constructors
static member-functions
member templates (see later)
2-71
// ...
class Figure {
public:
virtual double surface() const;
virtual void rotate();
};
13/06/09 15:56
2-72
18
(1)
Static composition
Different composites cannot share the component
The composite is responsible for its components,
it owns them
The lifetimes of the composite and its components are identical
13/06/09 15:56
2-73
(2)
class B { };
class A {
B _b;
// by value
B* _pb;
// by pointer
B& _rb;
// by reference
public:
A(const B& b1, B& b2)
: _b(b1),
_pb(&b2), _rb(b2)
{}
};
13/06/09 15:56
_b
_pb
_rb
During A construction, b1 is
copied into _b (by B copy
constructor: value semantics)
During A destruction, the
destructor of B will be
invoked
2-74
Creation
Implementation
13/06/09 15:56
2-75
19
Advanced C++
13/06/09 15:56
3-1
Exceptions
Motivation
13/06/09 15:56
13/06/09 15:56
3-2
Exceptions
Basic mechanism
Exceptions
Generic functions and classes (template)
Run Time Type Information (RTTI)
ISO C++ casts
Multiple inheritance
Miscellaneous ISO C++ extensions
Pointers to class members
Name packaging (namespace)
3-3
main() {f();}
void f() {
try {
...
g();
}
catch (E1) {...};
catch (E2) {...}
}
void g() {
try {
...
h();
}
catch (E1) {...}
}
void h() {
if (...) throw E1();
else throw E2();
}
13/06/09 15:56
3-4
Exceptions
Basic mechanism: destruction of locals
void f() {
try {
string s;
g();
...
deletion of s
}
catch (E1) {...};
}
deletion of s1
void g() {
string s1("hello");
h();
...
}
deletion of s2
void h() {
string s2("salut");
...
if (...) throw E1();
}
13/06/09 15:56
Exceptions
Basic mechanism: rethrowing an exception
main() {f();}
If a function is traversed by a
propagated exception, all
automatic (local) objects are
properly destroyed (i.e., their
destructor gets invoked)
Nothing similar happens for
dynamically allocated objects
(those allocated by new)
Thus it is the programmers
responsibility to provoke the
destruction of dynamically
allocated objects (see later)
void f() {
try {
...
g();
}
catch (E1) {...};
}
void g() {
rethrow
try {
...
h();
}
catch (E1) {...; throw;}
}
3-5
13/06/09 15:56
3-7
3-6
(1)
Exceptions
Throwing exception in a constructor
13/06/09 15:56
void h() {
if (...) throw E1();
}
Exceptions
Basic mechanism: uncaught exception
13/06/09 15:56
3-8
Exceptions
Throwing exception in 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 Exc_A2();
}
};
class B : public A1, public A2 {
string name;
public:
B(const string& s, int v)
: A1(s), A2(v) {
name = s; throw Exc_B();
}
};
13/06/09 15:56
(2)
v0
!
!
!
!
name
(~string())
~B()
~A1()
~A2()
3-9
13/06/09 15:56
3-11
(5)
3-10
Exceptions
Throwing exception in a constructor
13/06/09 15:56
(4)
(3)
v=0
Exceptions
Throwing exception in a constructor
Exceptions
Throwing exception in a constructor
13/06/09 15:56
3-12
Exceptions
Throw list
Exceptions
Throw list, virtual functions, and inheritance
class A {
public:
virtual void f1();
virtual void f2() throw (E1);
virtual void f3()
throw (E1, E2);
virtual void f4()
throw (E1, E2);
class E1 {};
class E2 {};
class DE1 : public E1 {};
13/06/09 15:56
3-13
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
My_Exception
System_Exc
Arithmetic_Exc
Overflow
IO_Exc
File_Exc
13/06/09 15:56
Network_Exc
File_Network_Exc
3-15
13/06/09 15:56
Underflow
Zero_Div
Exceptions
Organizing exceptions: catch resolution(2)
class B : public A {
public:
void f1() throw ();
void f2() throw (DE1);
void f3() throw (E2);
13/06/09 15:56
Exceptions
Organizing exceptions: catch resolution(1)
try {
// ...
}
catch (Overflow& ov) { }
catch (Arithmetic_Exc& e) {
cout << e.what();
}
catch (File_Exc) { }
catch (IO_Exc) { }
catch (...) {
cout << "unexpected";
}
3-16
Exceptions
Organizing exceptions: exception
Exceptions
Organizing exceptions: exception
(1)
exception
13/06/09 15:56
domain_err
3-17
overflow_err
invalid_argument
length_err
range_err
out_of_range
13/06/09 15:56
Exceptions
Resource Acquisition is Initialization
class Stack {
public:
class Any_Exc : public My_Exception { };
class Full : public Exc { };
class Empty : public Exc { };
// ...
void push(int);
// ...
};
void f1()
{
FILE *fp = fopen("toto", "w");
// ...
fclose(fp);
}
void f2()
{
A *p = new A();
// ...
delete p;
}
void f3()
{
lock(&mutex);
// ...
unlock(&mutex);
}
try {
st.push(v);
}
catch (Stack::Full) { }
catch (Stack::Any_Exc) { }
2005-2006 Jean-Paul Rigault
runtime_err
logic_err
Exceptions
Organizing exceptions: naming scheme
13/06/09 15:56
(2)
3-19
13/06/09 15:56
3-18
(1)
3-20
Exceptions
Resource Acquisition is Initialization
class My_File {
FILE *fp;
public:
My_File(...) {fp = fopen(...);}
~My_File() {fclose(fp);}
// ...
};
void f1()
{
My_File mf("toto", "r");
// ...
// No need to close
}
class My_Handle {
A *p;
public:
My_Handle(...) {p = new A(...);}
~My_Handle() {delete p;}
// ...
};
void f2()
{
My_Handle h(...);
// ...
// No need to delete
}
class My_Lock {
Mutex *_m;
public:
My_Lock(Mutex *m) :_m(m) {lock(_m);}
~My_Lock() {unlock(_m);}
// ...
};
void f3()
{
My_Lock l(&mutex);
// ...
// No need to unlock
}
13/06/09 15:56
(2)
3-21
13/06/09 15:56
3-22
13/06/09 15:56
Exceptions
Exception are for exceptional situations!
(2)
Nothrow guarantee
Some tips
Strong guarantee
(1)
Basic guarantee
Exceptions
Exception-safe code
Exceptions
Exception-safe code
3-23
try {
read(fd, &data_size, sizeof(int));
read(fd, buffer, data_size);
}
catch(End_Of_File) {...}
13/06/09 15:56
3-24
13/06/09 15:56
3-25
13/06/09 15:56
int i, j;
double x, y;
j = Min(i, 3); // int Min(int, int)
y = Min(x, y); // double Min(double, double)
Implicit instantiation is within the responsibility of overloading
resolution
3-26
3-27
13/06/09 15:56
13/06/09 15:56
3-28
Argument deduction
3-29
Lvalue transformation
Qualification adjustment
13/06/09 15:56
13/06/09 15:56
Candidate functions
// identity match
// qualification
3-30
Viable functions
Best match
Unchanged
Prefer non-template over template in case of equal ranking
3-31
13/06/09 15:56
3-32
13/06/09 15:56
3-33
13/06/09 15:56
3-34
(2)
template <typename Elem>
class List {
public:
List();
void append(const Elem& e);
void prepend(const Elem& e);
// ...
};
13/06/09 15:56
3-36
3-37
13/06/09 15:56
13/06/09 15:56
3-39
3-38
Hence, French * is
implicitely convertible into
Human *
13/06/09 15:56
3-40
10
class A {
// ...
T f(T1, T2, ..., Tn);
// ...
};
(1)
13/06/09 15:56
void f() {
A<int> ai;
A<string> as;
A<A<double> > aad;
ai._i = 10;
as._i = 10;
aad._i = 10; // OK
}
class B : public A {
// ...
T f(T1, T2, ..., Tn);
// ...
};
3-41
13/06/09 15:56
int main() {
A<string> as;
f(as);
}
2005-2006 Jean-Paul Rigault
3-43
// OK
// OK
3-42
13/06/09 15:56
13/06/09 15:56
3-44
11
(1)
A a;
a.mt(3);
a.mt("hello");
a.mt(3.5);
13/06/09 15:56
3-45
13/06/09 15:56
// A<int>::mt(char *)
3-46
13/06/09 15:56
class A {
template <typename U> friend void tf(U u);
// ...
};
template <typename U> void tf(U u, ...) { ... }
// A::mt(int)
// A::mt(char *)
// A::mt(double)
(2)
3-47
13/06/09 15:56
3-48
12
class A {
template <typename>
friend class F;
private:
int _i;
};
template <typename T>
class B {
template <typename>
friend class F;
private:
T _t;
};
13/06/09 15:56
(1)
int main() {
F<double> fr;
fr.m(); // OK
}
2005-2006 Jean-Paul Rigault
3-49
13/06/09 15:56
// Fixed_Array<double, 10>
// Fixed_Array<int, 10>
void f() {
class L { ... };
A<L> a; // NO
}
But not for classe templates only, not for function templates
3-50
13/06/09 15:56
3-51
13/06/09 15:56
// NO
3-52
13
13/06/09 15:56
3-53
3-55
2. At instantiation
13/06/09 15:56
3-54
13/06/09 15:56
Point of instantiation:
where the compiler inserts
the substituted template
definition
Look up dependent names
2-phase lookup
13/06/09 15:56
Independent name
A name that does not
depend on any template
parameter
Dependent name
A name that explicitly depend
on (some) template
parameters
T::A
A<T>
A<T>::_i
C::m<T>
3-56
14
13/06/09 15:56
//
3-57
13/06/09 15:56
13/06/09 15:56
(2)
Inclusion model
3-58
Separation model
is immaterial
(1)
Put everything into the .h file or, equivalently, include the .cpp
file at the end of the .h file?
As of now, this is the safest way
3-59
13/06/09 15:56
3-60
15
command-line option
13/06/09 15:56
(3)
In file A.h
export template <typename T>
class Stack {
public:
void push(T);
T pop();
file1.cpp
file2.cpp
file3.cpp
List<int> l1;
List<double> l2;
List<string> l3;
...
List<int> l1;
List<string> l2;
...
List<int> l1;
List<double> l2;
...
};
In file A.cpp
#include "A.h
template <typename T>
void Stack<T>::push(T t)
{ ... }
template <typename T>
void Stack<T>::pop(T t)
{ ... }
3-61
13/06/09 15:56
cfront, the first C++ compiler from AT&T used this technique
the pre-link phase may be very long
3-62
13/06/09 15:56
3-63
13/06/09 15:56
3-64
16
class B : public A {
public:
void f(); // no f() in A
};
class List<int>;
generate the whole implementation
void List<double>::append(const int&);
int Min<int>(int, int);
3-65
13/06/09 15:56
(1)
3-66
13/06/09 15:56
Remarks
(2)
class A { ... };
13/06/09 15:56
(1)
3-67
13/06/09 15:56
3-68
17
(2)
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
char *p = dynamic_cast<char*>(pf1);
// does not compile since char is
// not polymorphic
3-69
13/06/09 15:56
13/06/09 15:56
3-70
class type_info {
public:
virtual ~type_info();
bool operator==(const type_info&) const;
bool operator!=(const type_info&) const;
bool before(const type_info&) const; // !!
const char *name() const;
// No public constructor
// No public copy operator
};
pc = dynamic_cast<Circle *>(pf1);
// pc != 0
3-71
typeid(pf) == typeid(Figure *)
typeid(*pf) == typeid(Circle)
// yes
// yes
typeid(pf) == typeid(Ellipse *)
typeid(pf) == typeid(Circle *)
typeid(*pf) == typeid(Figure)
typeid(*pf) == typeid(Ellipse)
//
//
//
//
13/06/09 15:56
no
no
no
no
3-72
18
13/06/09 15:56
3-73
13/06/09 15:56
Operator dynamic_cast is
nice!
It has a greppable syntax
It has a perfectly defined (and
unique) purpose
13/06/09 15:56
3-74
dynamic_cast
the only cast that uses
dynamic information
static_cast
safe if compile-time
information is enough to
perform the cast
reinterpret_cast
convert between pointer
types or between pointers
and integers
const_cast
remove const!
T1 t1;
T2 t2 = static_cast<T2>(t1);
3-75
This cast is absolutely safe and the result is always correct if the
cast forces an implicit conversion
13/06/09 15:56
3-76
19
T1 t1;
T2 t2 = reinterpret_cast<T2>(t1);
T1 and T2 may have any pointer type or, more generally, any
integral type
This cast is intrinsically unsafe
The cast does not change the value, but reinterpret it in a new
type
The only sensible use is as a conversion relay (convert into some
type then, later, back to the original type)
13/06/09 15:56
3-77
Multiple inheritance
Reminders
13/06/09 15:56
3-78
Multiple inheritance
Regular (non virtual) multiple inheritance (1)
13/06/09 15:56
3-79
C*
B1*
this pointer
adjustment
B1
B2
B1
B2*
B2
C own
members
13/06/09 15:56
3-80
20
Multiple inheritance
Regular (non virtual) multiple inheritance (2)
C*
B1*
this pointer
adjustment
B1
B2*
B2
Ambiguities?
Call to A members
Implicit conversion
to A
Default, since it costs
nothing!
virtual
B1
B2
13/06/09 15:56
B1
A
B2
B2 own
members
3-81
13/06/09 15:56
C c;
c.f(); // no longer ambiguous!
A *pa = static_cast<A *>(&c);
// no longer ambiguous!
class A {
public:
void f() {}
};
class B1 : public A {};
class B2 : public A {};
class C : public B1, public B2 {};
C c;
c.f(); // ambiguous!
static_cast<B1&>(c).f(); // OK
// or override f() in C
A *pa = static_cast<A *>(&c);
// ambiguous!
A *pa = static_cast<A*>(
static_cast<B1 *>(&c));
2005-2006 Jean-Paul Rigault
Multiple inheritance
Virtual multiple inheritance
(1)
class A {
public:
void f() {}
};
class B1 : virtual public A {};
class B2 : virtual public A {};
class C : public B1, public B2 {};
B2
C own
members
Multiple inheritance
Virtual multiple inheritance
A
A
B1
B1 own
members
13/06/09 15:56
Multiple inheritance
Regular (non virtual) multiple inheritance (3)
3-82
(2)
Example
class Vehicle {
public:
virtual double speed() const { }
// ...
};
class Plane : virtual public Vehicle {...};
class Boat : virtual public Vehicle {...};
class Sea_Plane : public Plane, public Boat {...};
// We suppose the previous derived classes
// do not redefine speed()
Sea_plane sp(...);
v = sp.speed();
// No ambiguity here
3-83
13/06/09 15:56
3-84
21
Multiple inheritance
Virtual multiple inheritance
??
virtual
B1
B2
13/06/09 15:56
struct A {
A() {}
};
struct B1 : virtual A {
B1() : A() {}
};
struct B2 : virtual A {
B2() : A() {}
};
struct C : B1, B2 {
C() : A(), B1(), B2() {}
};
Multiple inheritance
Virtual multiple inheritance
(3)
virtual
B1
B2
3-85
(5)
Multiple inheritance
Virtual multiple inheritance
Construction of a virtual base class
struct A {
A() {}
};
struct B1 : virtual A {
B1() : A() {}
};
struct B2 : virtual A {
B2() : A() {}
};
struct C : B1, B2 {
C() : A(), B1(), B2() {}
};
2005-2006 Jean-Paul Rigault
13/06/09 15:56
3-86
Multiple inheritance
Virtual multiple inheritance
A* C*
B1* B2*
B1
(6)
A
B1 own
members
B2 own
members
offset
adjustment
virtual
(4)
B2
B2::m
B1
B2
C own
members
3-87
13/06/09 15:56
3-88
22
Multiple inheritance
Virtual multiple inheritance
(7)
virtual
B1
Multiple inheritance
Virtual multiple inheritance
B2
virtual
(8)
C1
D
13/06/09 15:56
3-89
and
and_eq
asm
auto
bitand
bitor
continue
default
delete
do
double
dynamic_cast
if
inline
int
long
mutable
namespace
register
reinterpret_cast
return
short
signed
sizeof
typedef
typeid
typename
union
unsigned
using
bool
break
case
catch
char
class
else
enum
explicit
extern
false
float
new
not
not_eq
operator
or
or_eq
static
static_cast
struct
switch
template
this
virtual
void
volatile
wchar_t
while
xor
compl
const
const_cast
for
friend
goto
private
protected
public
throw
true
try
xor_eq
struct
13/06/09 15:56
3-90
13/06/09 15:56
3-91
already in Ansi C
13/06/09 15:56
bitand
class
specific to C++
3-92
23
Digraphs
(C++ specific)
Trigraph
Replacement for
Trigraph
Replacement for
Digraph
Equivalent to
??=
??!
<%
??/
??<
%>
??
??>
<:
??(
??-
:>
??)
%:
13/06/09 15:56
3-93
13/06/09 15:56
class A {
public:
explicit A(int);
// ...
};
a = 5;
// implicit user conversion A(5) forbidden
A a = 3; // NO
A a(3); // OK
A a = A(3); // a complicated form for the previous
a = A(5);// OK
2005-2006 Jean-Paul Rigault
3-94
13/06/09 15:56
3-95
13/06/09 15:56
3-96
24
class Table {
const static int N = 10;
// OK
int t[N];
// OK
};
These are the only members that can be initialized on the fly
Note that they must be at the same time const, static, and
of some integral type
13/06/09 15:56
3-97
class A {
T f(int, double);
};
class U : public T {
// ...
};
class B : public A {
U f(int, double);
};
13/06/09 15:56
(1)
class Window {
int width, height;
int cursor_x, cursor_y;
public:
void up();
void down();
void right();
void left();
void repeat( ??? , int n);
};
2005-2006 Jean-Paul Rigault
class T {
// ...
};
3-98
13/06/09 15:56
(2)
void (Window::*)()
3-99
13/06/09 15:56
3-100
25
(3)
class A {
int x;
int y;
// ...
};
13/06/09 15:56
3-101
13/06/09 15:56
3-102
class A {
int x;
// ...
};
class B : public A { ... };
13/06/09 15:56
3-103
13/06/09 15:56
3-104
26
namespace My_Lib {
class List {...};
void f(int, double);
int f(char);
// ...
}
13/06/09 15:56
3-105
13/06/09 15:56
Explicit qualification
Using declaration
using My_Lib::f;
f(3, 12.5);
int i = f('a');
My_Lib::List l;
My_Lib::f(3, 12.5);
int i = My_Lib::f('a');
// import name f
(1)
Using directive
3-106
3-107
13/06/09 15:56
3-108
27
13/06/09 15:56
3-109
Regular lookup
Namespaces
form just
another nesting
hierarchy
The using
directives and
declarations
import the
corresponding
names into
another
namespace
13/06/09 15:56
13/06/09 15:56
(1)
(2)
int main() {
X::A a;
f(a);
X::f(a);
std::cout << a;
X::operator<<(std::cout, a);
// not very nice, is it?
}
... id ...
(2)
namespace X {
class A { ... };
void f(A a);
std::ostream&
operator<<(std::ostream& os, A a);
}
3-110
3-111
13/06/09 15:56
3-112
28
namespace X {
class A { ... };
void f(A a);
std::ostream&
operator<<(std::ostream& os, A a);
}
(4)
int main() {
X::A a;
f(a); // ADL finds X::f
std::cout << a;
// ADL finds X::operator<<
namespace X {
template <typename T>
void f(T t) { ... }
}
namespace Y {
using namespace X;
class A { ... };
}
int main() {
Y::A a;
f(a); // f not found
Y::f(a); // f found by regular lookup
std::string s;
std::cout << s << std::endl;
// ADL finds std::operator<<
// for string and endl
}
13/06/09 15:56
Agument dependent
lookup (ADL) (cont.)
Since the nondependent names are
looked up in the union
of regular look up and
ADL, there are possible
ambiguities
3-113
13/06/09 15:56
(5)
#include ...
using namespace std;
3-115
13/06/09 15:56
3-114
(6)
namespace X {
void f(int);
namespace Y {
void
//
void
//
13/06/09 15:56
f(double);
this f hides the one above
g() { f(3);}
always call Y::f(double)
}
}
int main() {
X::Y::g(); // calls X::Y::f
using namespace X;
using namespace X::Y;
f(3); // calls X::f
g(); // still calls X::Y::f
}
3-116
29
(7)
namespace X {
void f(int);
namespace Y {
using X::f;
void f(double);
// now f is overloaded
void g() { f(3);}
// calls X::f(int)
}
int main() {
X::Y::g();
using namespace X::Y;
f(3); // calls X::f
f(3.5); // calls X::Y::f
g(); // calls X::f
}
13/06/09 15:56
3-117
3-119
class A {
public:
void f(char);
};
class B : public A {
public:
13/06/09 15:56
(2)
13/06/09 15:56
(1)
3-118
(3)
13/06/09 15:56
3-120
30
(4)
class A {
public:
void f(char);
};
class C : private A {
public:
(5)
};
c b;
c.f('a'); // f(char) is not accessible
13/06/09 15:56
3-121
13/06/09 15:56
3-122
31
Advanced C++
13/06/09 15:57
4-1
13/06/09 15:57
Implementation limits
Standard function with a machine-dependent optimal
implementation
4-3
Type-safe
13/06/09 15:57
4-2
13/06/09 15:57
4-4
Namespace std
Header files
Utilities
Class pair
Library elements
13/06/09 15:57
4-5
Constructor is explicit
auto_ptr<A> ap = new A(...);
// Forbidden
13/06/09 15:57
Utilities
Class auto_ptr
#include <memory>
void f() {
auto_ptr<A> ap(new A(...));
// use ap as a pointer
// Pointed to object automatically deleted
}
13/06/09 15:57
(1)
Other operations
Equality, relational operators
Convenience function template make_pair
Utilities
Class auto_ptr
Couple of values
4-7
4-6
(2)
auto_ptr<A> ap1(new A());
void f(auto_ptr<A> ap) {
// ...
// object owned by ap deleted
}
ap1 = auto_ptr<A>(new A());
// Object previously owned by
// ap1 is deleted and ap1
// becomes owner of new one
f(ap1);
// ap1 has lost ownership and
// is now null!!
13/06/09 15:57
4-8
Utilities
Various utilities
4-9
deque<T>
<deque>
list<T>
<list>
<stack>
queue<T>
<queue>
priority_queue<T> <queue>
begin()
(1)
iterator
p
--
rbegin()
end()
++
*p
list<int> L;
for (int i = 0; i < N; i++) L.push_front(i);
list<int>::const_iterator it;
for (it = L.begin(); it != L.end(); ++it)
cout << *it << ' ';
Associative containers
map<K, T>
<map>
multimap<K, T>
<map>
set<K>
<set>
multiset<K>
<set>
13/06/09 15:57
4-10
rend()
13/06/09 15:57
template <typename T,
typename Allocator = allocator<T> >
class list {...};
13/06/09 15:57
Homogeneous contents
Homogeneous interface
4-11
13/06/09 15:57
4-12
(2)
Reverse iteration
list<int>::const_reverse_iterator rit;
for (rit = L.rbegin(); rit != L.rend(); ++rit)
cout << *rit << ' ';
list<int>::reverse_iterator rit;
for (rit = L.rbegin(); rit != L.rend(); rit++)
*rit = 10;
13/06/09 15:57
4-13
Input iterator
Move forward only (++)
Provide read only access
Cannot process the same
element several times
Output iterator
Move forward only
Provide read/write access
Do not have comparison
operators
Forward iterator
Both input and output
Have comparison operators
13/06/09 15:57
4-14
Bidirectional iterator
Move both ways (++, --)
Random access iterators
Bidirectional
Have arithmetic and
comparison operators
Iterator ranges always include left bound and exclude right one
([ [)
13/06/09 15:57
(3)
4-15
13/06/09 15:57
4-16
(2)
Contruction and destruction
Member types
Cont::value_type
type of element
Cont c;
Cont::iterator
value_type*
Cont c1(c2);
Cont::const_iterator
const value_type*
Cont::reverse_iterator
value_type*
Cont c(beg,end);
Cont::const_reverse_iterator
const value_type*
c.~Cont()
Destructor
Cont::reference
value_type&
Cont::const_reference
const value_type&
Cont::allocator_type
13/06/09 15:57
Size operations
4-17
(3)
Comparisons
c1 == c2
c.empty()
c.max_size()
13/06/09 15:57
4-18
(4)
Iterator interface
Are the two containers equal (all their elements are
pairwise equal)
c1 != c2
c1 < c2
(and <=, >, >= )
c.begin()
c.end()
c.rbegin()
c.rend()
Assignments
c1 = c2
c1.swap(c2)
swap(c1,c2)
Equivalent to c1.swap(c2)
13/06/09 15:57
c.size()
4-19
c.insert(pos,e)
c.erase(beg,end)
c.clear()
13/06/09 15:57
4-20
(1)
v
dq
Cont c(n);
"
" "
c.at(i)
Cont c(n,e);
"
"
"
c[i]
c.capacity()
"
"
"
c.front()
c.reserve(n)
"
"
c.back()
" "
dq
"
dq
c.resize(n)
c.resize(n,e)
Set values
(2)
c.assign(n)
c.assign(n,e)
"
13/06/09 15:57
"
4-21
"
(3)
v
dq
"
Access to elements
Resize
13/06/09 15:57
dq
4-22
c.unique(op)
c1.splice(pos,c2)
c1.splice
(pos,c2,beg,end)
c.push_back(e)
Append element e
c.pop_back()
c.sort()
c.push_front(e)
Prepend element e
"
" "
c.sort(op)
c.pop_front(e)
"
" "
c1.merge(c2)
c1.merge(c2,op)
c1.reverse()
Reverse list c1
c.erase(pos)
13/06/09 15:57
4-23
13/06/09 15:57
4-24
pq
c.push(e)
c.pop()
Remove an element
c.top()
" "
c.front()
"
c.back()
"
" "
" "
4-25
K, typename T,
Comp = less<K> > class map;
K, typename T,
Comp = less<K> > class
13/06/09 15:57
13/06/09 15:57
4-26
Cont c(op);
Cont
c(beg,end,op);
Accessors
Construction
template <typename
typename
template <typename
typename
multimap;
13/06/09 15:57
4-27
c.count(k)
c.find(k)
c.lower_bound(k)
c.upper_bound(k)
c.equal_range(k)
13/06/09 15:57
4-28
(5)
Insertion and removal
c.insert(k)
c.insert(beg,end)
c.erase(k)
c.erase(pos)
You cannot change the value of the key, since it is used to sort
the elements
13/06/09 15:57
4-29
Maps only
13/06/09 15:57
//
//
//
//
//
initially empty
new element ("hello", 3)
print 3
allocate new element
("bye", 0) and print 0
Default constructor
4-31
Vectors
Copy operations
For ordered containers, less than operator (<)
Sets
No set operations (union, intersection)
4-30
13/06/09 15:57
13/06/09 15:57
4-32
Insertion anywhere
O(1)
O(n)+
vector
list
deque
O(1)
Algorithms
Operation on head
O(1)
O(1)
O(1)
O(n)
O(1)
O(1)
O(n)
queue
O(n)
O(1)
O(log n)
O(log n)
map
O(log n)+
O(log n)+
set
O(log n)+
O(1)
array
O(1)
valarray
O(1)
bitset
O(1)
13/06/09 15:57
O(1)
O(n)+
O(n)+
O(1)+
4-33
4-34
(2)
Filtering a sequence
bool is_gt_4(int i) {
return i > 4;
}
list<int> L;
list<int>::iterator it =
find(L.begin(), L.end(), 7);
Algorithms
Algorithms on Sequences
13/06/09 15:57
(1)
Use iterators
Non-modifying algorithms
Modifying algorithms
O(1)
Algorithms
Algorithms on Sequences
O(log n)+
string
O(log n)+
multimap
multiset
O(1)+
stack
priority_queue
Operation on tail
list<int> L;
int n = count_if(L.begin(), L.end(), is_gt_4);
list<int> L;
list<int>::iterator it =
find(L.begin(), L.end(), 7);
13/06/09 15:57
4-35
13/06/09 15:57
4-36
Algorithms
Algorithms on Sequences/Sets
Algorithms
Function-Objects
(3)
Transforming a sequence
int length(string s) {
return s.size();
}
(1)
}
13/06/09 15:57
Algorithms
Function-Objects
Algorithms on Sequences/Sets
Function-Objects
13/06/09 15:57
(2)
4-37
4-38
(3)
A class of function-objects
bool pred(InputIterator::value_type)
4-39
13/06/09 15:57
4-40
10
Algorithms on Sequences/Sets
Function-objects
Algorithms on Sequences/Sets
Functionals
(4)
class Figure {
public:
void draw() const;
void rotate(int angle);
// ...
};
list<Figure> LF;
for_each(LF.begin(), LF.end(), &Figure::draw);
Predefined function-objects
negate<type>(p)
-- p
plus<type>(p1, p2)
p1 + p2
and minus, multiplies, divides, modulus
equal_to<type>(p1, p2)
p1 == p2
and not_equal_to
less<type>(p1, p2)
p1 < p2
and greater, less_equal, greater_equal
logical_not<type>(p)
!p
logical_and<type>(p1, p2) p1 && p2
and logical_or
13/06/09 15:57
Algorithms on Sequences/Sets
Functionals
4-41
13/06/09 15:57
4-43
4-42
(3)
Algorithms on Sequences/Sets
Functionals
Error !
13/06/09 15:57
(2)
for_each(LF.begin(), LF.end(),
mem_fun_ref(&Figure::draw));
(1)
it = find_if(l.begin(), l.end(),
bind2nd(greater<int>(), 35));
bind1st and bind2nd bind respectively the first and the
second parameter of a 2 parameters function-object , yielding a
function-object with one parameter less
not1 and not2 return the logical_not of a function-object
returning a boolean (respectively with 1 or 2 parameters)
13/06/09 15:57
4-44
11
Algorithms on Sequences/Sets
Functionals
(4)
Algorithms on Sequences/Sets
Functionals
Algorithms on Sequences/Sets
Functionals
4-45
4-47
4-46
(1)
Modify neither the collection itself nor the value of the elements
Require associated operations on the elements (equality, comparison...)
for_each()
count()
count_if
min_element()
max_element()
equal()
mismatch()
lexicographical_
compare()
13/06/09 15:57
Algorithms
Non-Modifying Algorithms
13/06/09 15:57
(6)
mem_fun(pm)
13/06/09 15:57
mem_fun_ref(pm)
(5)
13/06/09 15:57
4-48
12
Algorithms
Non-Modifying Algorithms
find()
find_if()
search_n()
search()
find_end()
find_first_of()
adjacent_find()
Algorithms
Modifying Algorithms
(2)
13/06/09 15:57
Algorithms
Modifying Algorithms
4-49
Sorting algorithms
Special form of mutating
algorithms
Sort a collection
Sorted range algorithms
Only operate on sorted
collections
Numeric algorithms
Apply numeric operations
on collections
Algorithms
Modifying Algorithms
4-50
(3)
Insert iterators
13/06/09 15:57
13/06/09 15:57
Mutating algorithms
Change the order of
elements
(2)
(1)
4-51
13/06/09 15:57
4-52
13
Algorithms
Simple Modifying Algorithms
Algorithms
Removing Algorithms
for_each()
copy()
copy_backward()
transform()
merge()
swap_range()
fill()
fill_n()
remove_copy()
remove_copy_if()
unique()
generate()
generate_n()
unique_copy()
replace()
replace_if()
replace_copy()
replace_copy_if()
Same as above, except that the result goes into another collection
13/06/09 15:57
remove()
remove_if()
4-53
13/06/09 15:57
Algorithms
Mutating Algorithms
reverse()
reverse_copy()
rotate()
rotate_copy()
next_permutation()
prev_permutation()
random_shuffle()
partition()
stable_partition()
Algorithms
Sorting Algorithms
(1)
4-54
operator<() by default
or a binary predicate given as a (last) parameter of the
algorithm
13/06/09 15:57
4-55
13/06/09 15:57
4-56
14
Algorithms
Sorting Algorithms
sort()
stable_sort()
partial_sort()
partial_sort_copy()
nth_element()
make_heap()
push_heap()
pop_heap()
sort_heap()
partition()
stable_partition()
13/06/09 15:57
Algorithms
Sorted Range Algorithms
(2)
binary_search()
includes()
lower_bound()
upper_bound()
equal_range()
merge()
set_union()
set_intersection()
set_difference()
set_symetric_difference()
inplace_merge()
4-57
13/06/09 15:57
Algorithms
Numeric Algorithms
inner_product()
adjacent_difference()
partial_sum()
13/06/09 15:57
4-58
Character Strings
accumulate()
4-59
representation
comparison (collating sequence)
copy operations
input-output
13/06/09 15:57
4-60
15
Character Strings
Class basic_string
Character Strings
Example: strings as sequence
Template class
Usual properties
string basic_string<char>
vector<char> vc;
string s = "hello, world";
copy(s.begin(), s.end(), back_inserter(vc));
No substrings
Catenation (+, append)
Comparisons
13/06/09 15:57
4-61
13/06/09 15:57
ios_base
4-62
Input-Output Streams
Classification
Input-Output Streams
ios
streambuf
virtual
istream
ostream
iostream
ifstream istringstream
ostringstream
stringstream
13/06/09 15:57
4-63
13/06/09 15:57
ofstream
fstream
4-64
16
Input-Output Streams
Stream Manipulators
Input-Output Streams
Stream Iterators
Special operations
int x, y, z, t;
cout << x << flush;
cout << x << endl;
// print x in hexadecimal
vector<string> v;
copy(istream_iterator<string>(cin),
istream_iterator<string>(),
back_inserter(v));
copy(v.begin(), v.end(),
ostream_iterator<string>(cout, ---));
cout << oct << x << hex << y << dec << z;
cout << t;
// x printed in octal, y in hexadecimal,
// z in decimal, t in decimal too (last
// state of the stream)
13/06/09 15:57
4-65
13/06/09 15:57
13/06/09 15:57
4-67
(1)
4-66
Algorithms
Numerics
13/06/09 15:57
4-68
17
4-69
list
13/06/09 15:57
(1)
No resource leak
No violation of container invariants
13/06/09 15:57
(3)
Supplementary guarantees
(2)
4-70
(2)
Iterator validity
13/06/09 15:57
4-71
13/06/09 15:57
4-72
18
Header files
(1)
Containers
General utilities
<utility> <functional>
<memory> <ctime>
Iterators
<iterator>
13/06/09 15:57
Algorithms
Header files
<algorithm> <cstdlib>
Diagnostics
<stdexcept> <cassert>
<cerrno>
Strings
<string> <cctype>
<cwtype> <cstring>
<cwstring> <cstdlib>
4-73
(2)
Input-output
<iosfwd> <iostream>
<ios> <streambuf>
<istream> <ostream>
<iomanip> <sstream>
<cstdlib> <fstream>
<cstdio> <cwchar>
Localization
<locale> <clocale>
13/06/09 15:57
Run-time support
<limits> <climits>
<cfloat> <new>
<typeinfo> <exception>
<cstddef> <cstdarg>
<csetjmp> <cstdlib>
<ctime> <csignal>
Numerics
<complex> <valarray>
<numerics> <cmath>
<cstdlib>
4-74
19