Advanced C++ Programming
Advanced C++ Programming
Programming
generic
Conception
Development
Testing
Release Time
Introduction
The goal of this course is to provide some keys to
choose the design which:
What is a pointer ?
What is a class ?
What is inheritance ?
Outline
Miscellaneous
Object design
Resolving ambiguities: namespace
namespace Gocad1 { ANSI feature
class MainWindow{ … };
}
namespace Gocad2 {
class MainWindow{ … };
}
using Gocad2::MainWindow;
Gocad1::MainWindow window(…);
References or pointers ?
Goal: refer to objects
References are as cheap as pointers,
and more convenient
Rules:
• In function parameters, use
const T& var instead of T var
• A nil reference does not exist, so use pointers
whenever you would need ‘nil references’.
• pointers can be reassigned, references can’t.
#include <vector>
class Traced { Exercise
public: traced.h
Traced();
Traced( int parameter );
Traced( const Traced& rhs );
~Traced();
Traced& operator=( const Traced& rhs );
private:
int impl_;
};
Using std::vector;
Class Dummy {
execute_val( vector<Traced> flags );
execute_p( vector<Traced>* flags );
execute_ref( vector<Traced>& flags );
execute_cref( const vector<Traced>& flags );
};
Exercise
int main( int argc, char** argv ) { traced.cpp
cout << "Creating the vector of data" << endl;
vector<Traced> data(2);
data[0] = Traced(0); data[1] = Traced(1);
cout << "---------------------------\n" <<
endl;
Dummy dummy;
dummy.execute_val( data );
dummy.execute_ptr( &data );
dummy.execute_ref( data );
dummy.execute_cref( data );
return 1;
}
g++ -o Traced traced.cpp
./Traced
Exceptions
try {
// some code that might cause pbs
}
throw “message”
catch ( “message” ) {
// special processing “Doctor Watson”
}
Constructor and assignment
class String { file.h
public:
String( const char* value );
String( const String& rhs );
~String();
String& operator=( const String& rhs);
private:
char* data_;
};
int main() {
String s1 = “tutu”;
String s2( “toto” );
s2 = s1;
};
Implicit type conversions
class Rational {
Rational( int num, int denom = 1 );
double operator double() const;
};
void print_rational(
ostream& out, const Rational& fraction
) {
out << fraction->num() << “ / ” <<
fraction->denom() << endl;
}
int main( int argc, char** argv ) {
Rational r(1,2);
double d = .5 * r;
print_rational( cout, d );
return 1;
}
Avoiding implicit conversions
class Rational {
explicit Rational( ANSI feature
int num,
int denom = 1
);
operator double() const;
};
Overloading operators (I)
class Rational {
Rational operator+(
int lhs, const Rational& rhs
) { //… }
If the left-hand side of the expression is of a
different type, the operator MUST be a non-member
Modifying non const member in const
member
Downgrade the const member
Miscellaneous
Object design
What is OOP?
class Car {
public:
// Members can be accessed from any object
protected:
// Can only be accessed by Car and its derived objects
private:
// Can only be accessed by Car for its own use.
};
Aggregation or Composition?
4
Car Wheel Person Brain
A aggregates B A composes B
= =
B is part of A, but their B is part of A, and their
lifetimes may be different lifetimes are the same
Ex: cars
c and wheels, engine, Ex: person and brain, lung,
etc. etc.
Classes: Basic Design Rules
Hide all member variables
Hide implementation functions and data
Minimize the number of public member functions
Avoid default constructors
Avoid overloading (can be ambiguous)
GeomShape
“A circle is a shape”
Circle
In other words:
What is applies to a base class
applies to its derived classes
Employee
class Employee {
public :
virtual float income(); // 1000 Boss
};
Employee
class Employee {
public :
virtual float income() = 0; Boss
// not implemented
};
class Boss : public Employee {
public :
virtual float income(); // implemented
};
Public Inheritance Philosophy
Inheritance of Inheritance of the
the interface implementation
class Car {
private:
Engine engine_;
};
Inheritance and fonctions
can virtual pure virtual Constructor Destructor
have... function function is… is…
Isolated
No No public public
class
base Yes public
Yes/no public
class (must) virtual
pure Yes public
abstract Yes / no protected
class (must) virtual
Derived
Yes public
(concrete) No public
class (must) virtual
Polymorphism Mechanism
Base::vf1
Base Base::vf2
vtbl_
Base::vf3
Derived Derived::vf1
Base
vtbl_
Derived::vf3
Consequences
Never call a virtual function in a constructor
Type* static_cast<Type>(expression)
Type* const_cast<Type>(expression)
Type* dynamic_cast<Type>(expression)
Type* reinterpret_cast<Type>(expression)
Additional guidelines...
Avoid multiple inheritance: use composition
Examples:
Matrix operator +
Examples:
Statistics manager
Dynamic arrays
Return value optimization
A first try...
class Complex {
//
};
const Complex operator*(
const Complex& a, const Complex b
) {
Complex c;
c.set_real( a.real() * b.real() );
c.set_im( a.im() + b.im() );
return c;
}
Return value optimization
A second try...
class Complex {
//
};
const Complex& operator*(
const Complex& a, const Complex b
) {
Complex c;
c.set_real( a.real() * b.real() );
c.set_im( a.im() + b.im() );
return c;
}
Return value optimization
A last try...
class Complex {
//
};
const Complex operator*(
const Complex& a, const Complex b
) {
return Complex(
a.real() * b.real(),
a.im() + b.im()
);
}
...But don’t alter your code quality for that !!
Some rules...
Overload to avoid implicit type conversions (fine
tuning only)
Problem:
- dynamic memory allocation is time-consuming
- the number of elements is not known from the start
Proposal:
/**
* Sorts a List of objects of type T.
* T must provide order operators <
*/
template <class T> class ListSorter {
public :
ListSorter( List<T>& list );
void sort();
private :
List<T>& list_;
};
Functors
Goal: replace pointers to functions
How ?
[return type] operator()( [type param] );
Type checking
Supports inline functions
Example:
Generator
Unary Function
Binary function
Predicates
…
Generic Programming
Idea:
//…
};
Delegation to STORAGE:
- Burdens the STORAGE concept
- May end up with inconsistencies
Example: Matrix objects (3)
template <class LEAF> class Matrix {
public:
LEAF& leaf() {
return static_cast<LEAF&>( *this );
}
};
class SymmetricMatrix:
public Matrix<SymmetricMatrix> {
//…
};
Derived type is known at compile-time
Derived classes can define their own functions
Template Specialization
Void f() {
const int fact4 = Factorial<4>::value;
}
Application: metaprograms
Practical interest:
Example :
Expand loops in vector / tensor /matrix calculus
IV- Overview of the STL
Include files
#include <iostream>
#include <utility>
#include <complex>
#include <list>
#include <vector>
#include <map>
….
STL containers
std::vector<int> vect(30);
vect[2] = 3;
//…
for(
std::vector<int>::iterator it(vect.begin());
it != vect.end(); it++
){
int& cur_value = *it;
}
V- Some design patterns
Finite state machine
To solve a linear system of equations…
add equation coefficients one by one, then invert the matrix
Class TransactionBased {
public:
start_task1();
do_action1(…);
end_task1();
private:
enum State{ UNDEF=0, TASK1=2, TASK2 = 4};
};
Composite
Graphic
Singleton
static Singleton* instance()
Observer
Subject Observer
notify() update()
ConcreteObserver
Factory method
Creator
create_product() Product
ConcreteCreator ConcreteProduct
Conclusions
Concrete Applications...
Programming project